From 94e8c48220d3abf04bc0e3f197d16d196acc9079 Mon Sep 17 00:00:00 2001 From: David Anderson Date: Sun, 12 Jun 2011 20:58:43 +0000 Subject: [PATCH] - client: change --detach_phase_two (??) to --detach_console - eliminate compiler warnings (e.g. shadowed vars) in various places, mostly in client svn path=/trunk/boinc/; revision=23710 --- api/boinc_api.cpp | 10 +- apps/upper_case.cpp | 4 +- checkin_notes | 16 + client/acct_mgr.cpp | 8 +- client/acct_setup.cpp | 6 +- client/app_start.cpp | 6 +- client/client_state.cpp | 4 +- client/client_types.h | 6 +- client/coproc_detect.cpp | 55 +- client/cpu_sched.cpp | 6 +- client/cs_cmdline.cpp | 4 +- client/cs_notice.cpp | 2 +- client/cs_scheduler.cpp | 11 +- client/current_version.cpp | 2 +- client/gui_http.cpp | 2 +- client/gui_http.h | 2 +- client/http_curl.cpp | 165 ++- client/log_flags.cpp | 2 +- client/net_stats.cpp | 4 +- client/rr_sim.cpp | 18 +- client/time_stats.cpp | 4 +- client/work_fetch.cpp | 3 +- lib/cc_config.cpp | 2 +- samples/example_app/Makefile | 1 + samples/example_app/uc2.cpp | 4 +- samples/vboxwrapper/Makefile | 1 + samples/vboxwrapper/vbox.cpp | 1610 ++++++++++++++------------- samples/vboxwrapper/vboxwrapper.cpp | 432 +++---- samples/wrapper/Makefile | 1 + samples/wrapper/wrapper.cpp | 20 +- sched/sched_main.cpp | 4 +- 31 files changed, 1200 insertions(+), 1215 deletions(-) diff --git a/api/boinc_api.cpp b/api/boinc_api.cpp index 238d58542f..95c313c8a3 100644 --- a/api/boinc_api.cpp +++ b/api/boinc_api.cpp @@ -425,7 +425,7 @@ int boinc_init_options(BOINC_OPTIONS* opt) { // original process - master // options.send_status_msgs = false; - int retval = boinc_init_options_general(options); + retval = boinc_init_options_general(options); if (retval) { kill(child_pid, SIGKILL); return retval; @@ -454,10 +454,10 @@ int boinc_init_options(BOINC_OPTIONS* opt) { } int boinc_init_parallel() { - BOINC_OPTIONS options; - boinc_options_defaults(options); - options.multi_thread = true; - return boinc_init_options(&options); + BOINC_OPTIONS _options; + boinc_options_defaults(_options); + _options.multi_thread = true; + return boinc_init_options(&_options); } int boinc_init_options_general(BOINC_OPTIONS& opt) { diff --git a/apps/upper_case.cpp b/apps/upper_case.cpp index fdcbd06d18..7852eba6e3 100644 --- a/apps/upper_case.cpp +++ b/apps/upper_case.cpp @@ -216,7 +216,7 @@ int main(int argc, char **argv) { // main loop - read characters, convert to UC, write // - for (int i=0; ; i++) { + for (i=0; ; i++) { c = fgetc(infile); if (c == EOF) break; @@ -267,7 +267,7 @@ int main(int argc, char **argv) { // if (cpu_time) { double start = dtime(); - for (int i=0; ; i++) { + for (i=0; ; i++) { double e = dtime()-start; if (e > cpu_time) break; fd = .5 + .5*(e/cpu_time); diff --git a/checkin_notes b/checkin_notes index 5707879cf4..5a77a7774b 100644 --- a/checkin_notes +++ b/checkin_notes @@ -3474,3 +3474,19 @@ David 10 Jun 2011 client/ client_types.cpp + +David 12 Jun 2011 + - client: change --detach_phase_two (??) to --detach_console + - eliminate compiler warnings (e.g. shadowed vars) + in various places, mostly in client + + sched/ + sched_main.cpp + lib/ + cc_config.cpp + samples/ + many.cpp + client/ + many.cpp + api/ + boinc_api.cpp diff --git a/client/acct_mgr.cpp b/client/acct_mgr.cpp index f7334176a3..400d81f9e7 100644 --- a/client/acct_mgr.cpp +++ b/client/acct_mgr.cpp @@ -580,8 +580,8 @@ void ACCT_MGR_OP::handle_reply(int http_op_retval) { pp->abort_not_started(); } } - for (int i=0; ino_rsc_ams[i] = acct.no_rsc[i]; + for (int j=0; jno_rsc_ams[j] = acct.no_rsc[j]; } } } else { @@ -597,8 +597,8 @@ void ACCT_MGR_OP::handle_reply(int http_op_retval) { ); pp = gstate.lookup_project(acct.url.c_str()); if (pp) { - for (int i=0; ino_rsc_ams[i] = acct.no_rsc[i]; + for (int j=0; jno_rsc_ams[j] = acct.no_rsc[j]; } if (acct.dont_request_more_work.present) { pp->dont_request_more_work = acct.dont_request_more_work.value; diff --git a/client/acct_setup.cpp b/client/acct_setup.cpp index aa04824258..eef7b58287 100644 --- a/client/acct_setup.cpp +++ b/client/acct_setup.cpp @@ -106,7 +106,7 @@ int GET_PROJECT_CONFIG_OP::do_rpc(string master_url) { ); retval = gui_http->do_rpc( - this, (char*)url.c_str(), GET_PROJECT_CONFIG_FILENAME, false + this, url.c_str(), GET_PROJECT_CONFIG_FILENAME, false ); if (retval) { error_num = retval; @@ -143,7 +143,7 @@ int LOOKUP_ACCOUNT_OP::do_rpc(ACCOUNT_IN& ai) { url += parameter; retval = gui_http->do_rpc( - this, (char*)url.c_str(), LOOKUP_ACCOUNT_FILENAME, false + this, url.c_str(), LOOKUP_ACCOUNT_FILENAME, false ); if (retval) { error_num = retval; @@ -191,7 +191,7 @@ int CREATE_ACCOUNT_OP::do_rpc(ACCOUNT_IN& ai) { url += parameter; } retval = gui_http->do_rpc( - this, (char*)url.c_str(), CREATE_ACCOUNT_FILENAME, false + this, url.c_str(), CREATE_ACCOUNT_FILENAME, false ); if (retval) { error_num = retval; diff --git a/client/app_start.cpp b/client/app_start.cpp index df9a44b5c8..fcd193497b 100644 --- a/client/app_start.cpp +++ b/client/app_start.cpp @@ -906,9 +906,9 @@ int ACTIVE_TASK::start(bool first_time) { #endif #if defined (HAVE_SCHED_SETSCHEDULER) && defined(SCHED_BATCH) && defined (__linux__) if (!high_priority) { - struct sched_param p; - p.sched_priority = 0; - if (sched_setscheduler(0, SCHED_BATCH, &p)) { + struct sched_param sp; + sp.sched_priority = 0; + if (sched_setscheduler(0, SCHED_BATCH, &sp)) { perror("sched_setscheduler"); } } diff --git a/client/client_state.cpp b/client/client_state.cpp index 0f14530482..ddab0330ee 100644 --- a/client/client_state.cpp +++ b/client/client_state.cpp @@ -1750,8 +1750,8 @@ int CLIENT_STATE::reset_project(PROJECT* project, bool detaching) { project->ams_resource_share = -1; project->min_rpc_time = 0; project->pwf.reset(project); - for (int i=0; irsc_pwf[i].reset(); + for (int j=0; jrsc_pwf[j].reset(); } write_state_file(); return 0; diff --git a/client/client_types.h b/client/client_types.h index 677bf65572..a6d9efcdec 100644 --- a/client/client_types.h +++ b/client/client_types.h @@ -521,8 +521,6 @@ struct APP_VERSION { double avg_ncpus; double max_ncpus; GPU_USAGE gpu_usage; // can only use 1 GPUtype - //double ncudas; - //double natis; // remove double gpu_ram; double flops; char cmdline[256]; @@ -557,8 +555,8 @@ struct APP_VERSION { void get_file_errors(std::string&); void clear_errors(); int api_major_version(); - inline bool uses_coproc(int rsc_type) { - return (gpu_usage.rsc_type == rsc_type); + inline bool uses_coproc(int rt) { + return (gpu_usage.rsc_type == rt); } inline int rsc_type() { return gpu_usage.rsc_type; diff --git a/client/coproc_detect.cpp b/client/coproc_detect.cpp index 0a4ca84c38..a4641ce8fb 100644 --- a/client/coproc_detect.cpp +++ b/client/coproc_detect.cpp @@ -683,7 +683,7 @@ void COPROC_NVIDIA::get( vector& warnings, vector& ignore_devs ) { - int count, retval; + int cuda_ndevs, retval; char buf[256]; #ifdef _WIN32 @@ -803,7 +803,6 @@ void COPROC_NVIDIA::get( return; } - int cuda_version; retval = (*__cuDriverGetVersion)(&cuda_version); if (retval) { sprintf(buf, "cuDriverGetVersion() returned %d", retval); @@ -812,20 +811,20 @@ void COPROC_NVIDIA::get( } vector gpus; - retval = (*__cuDeviceGetCount)(&count); + retval = (*__cuDeviceGetCount)(&cuda_ndevs); if (retval) { sprintf(buf, "cuDeviceGetCount() returned %d", retval); warnings.push_back(buf); return; } - sprintf(buf, "NVIDIA library reports %d GPU%s", count, (count==1)?"":"s"); + sprintf(buf, "NVIDIA library reports %d GPU%s", cuda_ndevs, (cuda_ndevs==1)?"":"s"); warnings.push_back(buf); int j; unsigned int i; COPROC_NVIDIA cc; string s; - for (j=0; j 0) { - best = gpus[i]; + } else if (nvidia_compare(gpus[i], *this, false) > 0) { + *this = gpus[i]; } } // see which other instances are equivalent, // and set the "count" and "device_nums" fields // - best.count = 0; + count = 0; for (i=0; i 0) { - best = gpus[i]; + } else if (ati_compare(gpus[i], *this, false) > 0) { + *this = gpus[i]; } } - best.count = 0; + count = 0; for (i=0; i attach to a project\n" " --check_all_logins for idle detection, check remote logins too\n" " --daemon run as daemon (Unix)\n" - " --detach detach from console (Windows)\n" + " --detach_console detach from console (Windows)\n" " --detach_project detach from a project\n" " --dir use given dir as BOINC home\n" " --exit_after_app_start N exit N seconds after an app starts\n" @@ -136,7 +136,7 @@ void CLIENT_STATE::parse_cmdline(int argc, char** argv) { check_all_logins = true; } else if (ARG(daemon)) { executing_as_daemon = true; - } else if (ARG(detach_phase_two)) { + } else if (ARG(detach_console)) { detach_console = true; } else if (ARG(detach_project)) { if (i == argc-1) show_options = true; diff --git a/client/cs_notice.cpp b/client/cs_notice.cpp index 2045bfa489..b0e6aacd77 100644 --- a/client/cs_notice.cpp +++ b/client/cs_notice.cpp @@ -649,7 +649,7 @@ int RSS_FEED::parse_items(XML_PARSER& xp, int& nitems) { if (!strcmp(tag, "item")) { NOTICE n; ntotal++; - int retval = n.parse_rss(xp); + retval = n.parse_rss(xp); if (retval) { nerror++; } else if (n.create_time < gstate.now - 30*86400) { diff --git a/client/cs_scheduler.cpp b/client/cs_scheduler.cpp index 5a1ec9b750..00ddcabd67 100644 --- a/client/cs_scheduler.cpp +++ b/client/cs_scheduler.cpp @@ -73,7 +73,6 @@ int CLIENT_STATE::make_scheduler_request(PROJECT* p) { MIOFILE mf; unsigned int i; RESULT* rp; - int retval; double disk_total, disk_project; get_sched_request_filename(*p, buf, sizeof(buf)); @@ -205,8 +204,7 @@ int CLIENT_STATE::make_scheduler_request(PROJECT* p) { // host_info.get_host_info(); set_ncpus(); - retval = host_info.write(mf, !config.suppress_net_info, false); - //if (retval) return retval; + host_info.write(mf, !config.suppress_net_info, false); // get and write disk usage // @@ -484,7 +482,7 @@ int CLIENT_STATE::handle_scheduler_reply(PROJECT* project, char* scheduler_url) int retval; unsigned int i; bool signature_valid, update_global_prefs=false, update_project_prefs=false; - char buf[256], filename[256]; + char buf[1024], filename[256]; std::string old_gui_urls = project->gui_urls; PROJECT* p2; vectornew_results; @@ -571,7 +569,6 @@ int CLIENT_STATE::handle_scheduler_reply(PROJECT* project, char* scheduler_url) for (i=0; ido_rpc( - this, (char*)config.client_version_check_url.c_str(), + this, config.client_version_check_url.c_str(), GET_CURRENT_VERSION_FILENAME, true ); diff --git a/client/gui_http.cpp b/client/gui_http.cpp index c90b840b4b..538ac52b0c 100644 --- a/client/gui_http.cpp +++ b/client/gui_http.cpp @@ -31,7 +31,7 @@ #include "gui_http.h" int GUI_HTTP::do_rpc( - GUI_HTTP_OP* op, char* url, const char* output_file, bool is_bkgd + GUI_HTTP_OP* op, const char* url, const char* output_file, bool is_bkgd ) { int retval; diff --git a/client/gui_http.h b/client/gui_http.h index 5bcec5ad7a..ec55789554 100644 --- a/client/gui_http.h +++ b/client/gui_http.h @@ -36,7 +36,7 @@ struct GUI_HTTP { GUI_HTTP(): gui_http_state(GUI_HTTP_STATE_IDLE) {} int do_rpc( - struct GUI_HTTP_OP*, char* url, const char* output_file, + struct GUI_HTTP_OP*, const char* url, const char* output_file, bool is_background ); int do_rpc_post( diff --git a/client/http_curl.cpp b/client/http_curl.cpp index 0fb2816ed7..b7ff8c40c4 100644 --- a/client/http_curl.cpp +++ b/client/http_curl.cpp @@ -390,7 +390,6 @@ int HTTP_OP::libcurl_exec( const char* url, const char* in, const char* out, double offset, bool bPost ) { CURLMcode curlMErr; - CURLcode curlErr; char strTmp[128]; static int outfile_seqno=0; @@ -421,10 +420,9 @@ int HTTP_OP::libcurl_exec( } // the following seems to be a no-op - //curlErr = curl_easy_setopt(curlEasy, CURLOPT_ERRORBUFFER, error_msg); - - curlErr = curl_easy_setopt(curlEasy, CURLOPT_URL, m_url); + // curl_easy_setopt(curlEasy, CURLOPT_ERRORBUFFER, error_msg); + curl_easy_setopt(curlEasy, CURLOPT_URL, m_url); // This option determines whether curl verifies that the server // claims to be who you want it to be. @@ -446,7 +444,7 @@ int HTTP_OP::libcurl_exec( // the server claims. The server could be lying. // To control lying, see CURLOPT_SSL_VERIFYPEER. // - curlErr = curl_easy_setopt(curlEasy, CURLOPT_SSL_VERIFYHOST, 2L); + curl_easy_setopt(curlEasy, CURLOPT_SSL_VERIFYHOST, 2L); // the following sets "tough" certificate checking // (i.e. whether self-signed is OK) @@ -454,7 +452,7 @@ int HTTP_OP::libcurl_exec( // (cert not 3rd party trusted) // if non-zero below, you need a valid 3rd party CA (i.e. Verisign, Thawte) // - curlErr = curl_easy_setopt(curlEasy, CURLOPT_SSL_VERIFYPEER, 1L); + curl_easy_setopt(curlEasy, CURLOPT_SSL_VERIFYPEER, 1L); // if the above is nonzero, you need the following: // @@ -492,7 +490,7 @@ int HTTP_OP::libcurl_exec( // call this only if a local copy of ca-bundle.crt exists; // otherwise, let's hope that it exists in the default place // - curlErr = curl_easy_setopt(curlEasy, CURLOPT_CAINFO, m_curl_ca_bundle_location); + curl_easy_setopt(curlEasy, CURLOPT_CAINFO, m_curl_ca_bundle_location); if (log_flags.http_debug) { msg_printf( 0, @@ -506,38 +504,38 @@ int HTTP_OP::libcurl_exec( // call this only if a local copy of ca-bundle.crt exists; // otherwise, let's hope that it exists in the default place // - curlErr = curl_easy_setopt(curlEasy, CURLOPT_CAINFO, CA_BUNDLE_FILENAME); + curl_easy_setopt(curlEasy, CURLOPT_CAINFO, CA_BUNDLE_FILENAME); } #endif // set the user agent as this boinc client & version // - curlErr = curl_easy_setopt(curlEasy, CURLOPT_USERAGENT, g_user_agent_string); + curl_easy_setopt(curlEasy, CURLOPT_USERAGENT, g_user_agent_string); // bypass any signal handlers that curl may want to install // - curlErr = curl_easy_setopt(curlEasy, CURLOPT_NOSIGNAL, 1L); + curl_easy_setopt(curlEasy, CURLOPT_NOSIGNAL, 1L); // bypass progress meter // - curlErr = curl_easy_setopt(curlEasy, CURLOPT_NOPROGRESS, 1L); + curl_easy_setopt(curlEasy, CURLOPT_NOPROGRESS, 1L); // setup timeouts // - curlErr = curl_easy_setopt(curlEasy, CURLOPT_TIMEOUT, 0L); - curlErr = curl_easy_setopt(curlEasy, CURLOPT_LOW_SPEED_LIMIT, config.http_transfer_timeout_bps); - curlErr = curl_easy_setopt(curlEasy, CURLOPT_LOW_SPEED_TIME, config.http_transfer_timeout); - curlErr = curl_easy_setopt(curlEasy, CURLOPT_CONNECTTIMEOUT, 120L); + curl_easy_setopt(curlEasy, CURLOPT_TIMEOUT, 0L); + curl_easy_setopt(curlEasy, CURLOPT_LOW_SPEED_LIMIT, config.http_transfer_timeout_bps); + curl_easy_setopt(curlEasy, CURLOPT_LOW_SPEED_TIME, config.http_transfer_timeout); + curl_easy_setopt(curlEasy, CURLOPT_CONNECTTIMEOUT, 120L); // force curl to use HTTP/1.0 if config specifies it // (curl uses 1.1 by default) // if (config.http_1_0 || (config.force_auth == "ntlm")) { - curlErr = curl_easy_setopt(curlEasy, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); + curl_easy_setopt(curlEasy, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_0); } - curlErr = curl_easy_setopt(curlEasy, CURLOPT_MAXREDIRS, 50L); - curlErr = curl_easy_setopt(curlEasy, CURLOPT_AUTOREFERER, 1L); - curlErr = curl_easy_setopt(curlEasy, CURLOPT_FOLLOWLOCATION, 1L); - curlErr = curl_easy_setopt(curlEasy, CURLOPT_POST301, 1L); + curl_easy_setopt(curlEasy, CURLOPT_MAXREDIRS, 50L); + curl_easy_setopt(curlEasy, CURLOPT_AUTOREFERER, 1L); + curl_easy_setopt(curlEasy, CURLOPT_FOLLOWLOCATION, 1L); + curl_easy_setopt(curlEasy, CURLOPT_POST301, 1L); // if we tell Curl to accept any encoding (e.g. deflate) // it seems to accept them all, which screws up projects that @@ -545,7 +543,7 @@ int HTTP_OP::libcurl_exec( // So, detect this and don't accept any encoding in that case // if (!out || !ends_with(std::string(out), std::string(".gz"))) { - curlErr = curl_easy_setopt(curlEasy, CURLOPT_ENCODING, ""); + curl_easy_setopt(curlEasy, CURLOPT_ENCODING, ""); } // setup any proxy they may need @@ -584,11 +582,11 @@ int HTTP_OP::libcurl_exec( // we can make the libcurl_write "fancier" in the future, // for now it just fwrite's to the file request, which is sufficient // - curlErr = curl_easy_setopt(curlEasy, CURLOPT_WRITEFUNCTION, libcurl_write); + curl_easy_setopt(curlEasy, CURLOPT_WRITEFUNCTION, libcurl_write); // note that in my lib_write I'm sending in a pointer // to this instance of HTTP_OP // - curlErr = curl_easy_setopt(curlEasy, CURLOPT_WRITEDATA, this); + curl_easy_setopt(curlEasy, CURLOPT_WRITEDATA, this); } if (bPost) { @@ -605,7 +603,7 @@ int HTTP_OP::libcurl_exec( } if (pcurlList) { // send custom headers if required - curlErr = curl_easy_setopt(curlEasy, CURLOPT_HTTPHEADER, pcurlList); + curl_easy_setopt(curlEasy, CURLOPT_HTTPHEADER, pcurlList); } // set the data file info to read for the PUT/POST @@ -614,11 +612,11 @@ int HTTP_OP::libcurl_exec( #if 0 // HTTP PUT method curl_off_t fs = (curl_off_t) content_length; - curlErr = curl_easy_setopt(curlEasy, CURLOPT_POSTFIELDS, NULL); - curlErr = curl_easy_setopt(curlEasy, CURLOPT_INFILESIZE, content_length); - curlErr = curl_easy_setopt(curlEasy, CURLOPT_READDATA, fileIn); - curlErr = curl_easy_setopt(curlEasy, CURLOPT_INFILESIZE_LARGE, fs); - curlErr = curl_easy_setopt(curlEasy, CURLOPT_PUT, 1L); + curl_easy_setopt(curlEasy, CURLOPT_POSTFIELDS, NULL); + curl_easy_setopt(curlEasy, CURLOPT_INFILESIZE, content_length); + curl_easy_setopt(curlEasy, CURLOPT_READDATA, fileIn); + curl_easy_setopt(curlEasy, CURLOPT_INFILESIZE_LARGE, fs); + curl_easy_setopt(curlEasy, CURLOPT_PUT, 1L); #endif // HTTP POST method @@ -631,14 +629,16 @@ int HTTP_OP::libcurl_exec( // pcurlFormStart = pcurlFormEnd = NULL; curl_formadd(&pcurlFormStart, &pcurlFormEnd, - CURLFORM_FILECONTENT, infile, - CURLFORM_CONTENTSLENGTH, content_length, - CURLFORM_CONTENTTYPE, g_content_type, - CURLFORM_END); + CURLFORM_FILECONTENT, infile, + CURLFORM_CONTENTSLENGTH, content_length, + CURLFORM_CONTENTTYPE, g_content_type, + CURLFORM_END + ); curl_formadd(&post, &last, - CURLFORM_COPYNAME, "logotype-image", - CURLFORM_FILECONTENT, "curl.png", CURLFORM_END); - curlErr = curl_easy_setopt(curlEasy, CURLOPT_HTTPPOST, pcurlFormStart); + CURLFORM_COPYNAME, "logotype-image", + CURLFORM_FILECONTENT, "curl.png", CURLFORM_END + ); + curl_easy_setopt(curlEasy, CURLOPT_HTTPPOST, pcurlFormStart); #endif curl_off_t fs = (curl_off_t) content_length; @@ -649,19 +649,19 @@ int HTTP_OP::libcurl_exec( // we can make the libcurl_read "fancier" in the future, // for now it just fwrite's to the file request, which is sufficient // - curlErr = curl_easy_setopt(curlEasy, CURLOPT_POSTFIELDS, NULL); - curlErr = curl_easy_setopt(curlEasy, CURLOPT_POSTFIELDSIZE_LARGE, fs); - curlErr = curl_easy_setopt(curlEasy, CURLOPT_READFUNCTION, libcurl_read); + curl_easy_setopt(curlEasy, CURLOPT_POSTFIELDS, NULL); + curl_easy_setopt(curlEasy, CURLOPT_POSTFIELDSIZE_LARGE, fs); + curl_easy_setopt(curlEasy, CURLOPT_READFUNCTION, libcurl_read); // in my lib_write I'm sending in a pointer to this instance of HTTP_OP // - curlErr = curl_easy_setopt(curlEasy, CURLOPT_READDATA, this); + curl_easy_setopt(curlEasy, CURLOPT_READDATA, this); // callback function to rewind input file // - curlErr = curl_easy_setopt(curlEasy, CURLOPT_IOCTLFUNCTION, libcurl_ioctl); - curlErr = curl_easy_setopt(curlEasy, CURLOPT_IOCTLDATA, this); + curl_easy_setopt(curlEasy, CURLOPT_IOCTLFUNCTION, libcurl_ioctl); + curl_easy_setopt(curlEasy, CURLOPT_IOCTLDATA, this); - curlErr = curl_easy_setopt(curlEasy, CURLOPT_POST, 1L); + curl_easy_setopt(curlEasy, CURLOPT_POST, 1L); } else { // GET want_upload = false; want_download = true; @@ -669,20 +669,20 @@ int HTTP_OP::libcurl_exec( // now write the header, pcurlList gets freed in net_xfer_curl // if (pcurlList) { // send custom headers if required - curlErr = curl_easy_setopt(curlEasy, CURLOPT_HTTPHEADER, pcurlList); + curl_easy_setopt(curlEasy, CURLOPT_HTTPHEADER, pcurlList); } // setup the GET! // - curlErr = curl_easy_setopt(curlEasy, CURLOPT_HTTPGET, 1L); + curl_easy_setopt(curlEasy, CURLOPT_HTTPGET, 1L); } // turn on debug info if tracing enabled // if (log_flags.http_debug) { - curlErr = curl_easy_setopt(curlEasy, CURLOPT_DEBUGFUNCTION, libcurl_debugfunction); - curlErr = curl_easy_setopt(curlEasy, CURLOPT_DEBUGDATA, this ); - curlErr = curl_easy_setopt(curlEasy, CURLOPT_VERBOSE, 1L); + curl_easy_setopt(curlEasy, CURLOPT_DEBUGFUNCTION, libcurl_debugfunction); + curl_easy_setopt(curlEasy, CURLOPT_DEBUGDATA, this ); + curl_easy_setopt(curlEasy, CURLOPT_VERBOSE, 1L); } // last but not least, add this to the curl_multi @@ -748,7 +748,6 @@ int HTTP_OP_SET::nops() { // CURLAUTH_GSSNEGOTIATE, CURLAUTH_NTLM, CURLAUTH_ANY, CURLAUTH_ANYSAFE // CURLOPT_PROXYAUTH -- "or" | the above bitmasks -- only basic, digest, ntlm work void HTTP_OP::setup_proxy_session(bool no_proxy) { - CURLcode curlErr; // CMC Note: the string m_curl_user_credentials must remain in memory // outside of this method (libcurl relies on it later when it makes @@ -757,7 +756,7 @@ void HTTP_OP::setup_proxy_session(bool no_proxy) { strcpy(m_curl_user_credentials, ""); if (no_proxy) { - curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXY, ""); + curl_easy_setopt(curlEasy, CURLOPT_PROXY, ""); return; } @@ -771,41 +770,41 @@ void HTTP_OP::setup_proxy_session(bool no_proxy) { } // setup a basic http proxy - curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); - curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYPORT, (long) pi.http_server_port); - curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXY, (char*) pi.http_server_name); + curl_easy_setopt(curlEasy, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); + curl_easy_setopt(curlEasy, CURLOPT_PROXYPORT, (long) pi.http_server_port); + curl_easy_setopt(curlEasy, CURLOPT_PROXY, (char*) pi.http_server_name); if (pi.use_http_auth) { if (config.force_auth == "basic") { - curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYAUTH, CURLAUTH_BASIC); + curl_easy_setopt(curlEasy, CURLOPT_PROXYAUTH, CURLAUTH_BASIC); } else if (config.force_auth == "digest") { - curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST); + curl_easy_setopt(curlEasy, CURLOPT_PROXYAUTH, CURLAUTH_DIGEST); } else if (config.force_auth == "gss-negotiate") { - curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYAUTH, CURLAUTH_GSSNEGOTIATE); + curl_easy_setopt(curlEasy, CURLOPT_PROXYAUTH, CURLAUTH_GSSNEGOTIATE); } else if (config.force_auth == "ntlm") { - curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYAUTH, CURLAUTH_NTLM); + curl_easy_setopt(curlEasy, CURLOPT_PROXYAUTH, CURLAUTH_NTLM); } else { - curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYAUTH, CURLAUTH_ANY); + curl_easy_setopt(curlEasy, CURLOPT_PROXYAUTH, CURLAUTH_ANY); } sprintf(m_curl_user_credentials, "%s:%s", pi.http_user_name, pi.http_user_passwd); - curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYUSERPWD, m_curl_user_credentials); + curl_easy_setopt(curlEasy, CURLOPT_PROXYUSERPWD, m_curl_user_credentials); } } else if (pi.use_socks_proxy) { // CURL only supports SOCKS version 5 - curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); - curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYPORT, (long) pi.socks_server_port); - curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXY, (char*) pi.socks_server_name); + curl_easy_setopt(curlEasy, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); + curl_easy_setopt(curlEasy, CURLOPT_PROXYPORT, (long) pi.socks_server_port); + curl_easy_setopt(curlEasy, CURLOPT_PROXY, (char*) pi.socks_server_name); // libcurl uses blocking sockets with socks proxy, so limit timeout. // - imlemented with local patch to libcurl - curlErr = curl_easy_setopt(curlEasy, CURLOPT_CONNECTTIMEOUT, 20L); + curl_easy_setopt(curlEasy, CURLOPT_CONNECTTIMEOUT, 20L); if ( strlen(pi.socks5_user_passwd) || strlen(pi.socks5_user_name) ) { sprintf(m_curl_user_credentials, "%s:%s", pi.socks5_user_name, pi.socks5_user_passwd); - curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYUSERPWD, m_curl_user_credentials); - curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYAUTH, CURLAUTH_ANY & ~CURLAUTH_NTLM); + curl_easy_setopt(curlEasy, CURLOPT_PROXYUSERPWD, m_curl_user_credentials); + curl_easy_setopt(curlEasy, CURLOPT_PROXYAUTH, CURLAUTH_ANY & ~CURLAUTH_NTLM); } } else if (pi.have_autodetect_proxy_settings && strlen(pi.autodetect_server_name)) { if (log_flags.proxy_debug) { @@ -817,16 +816,16 @@ void HTTP_OP::setup_proxy_session(bool no_proxy) { switch(pi.autodetect_protocol) { case URL_PROTOCOL_SOCKS: - curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); + curl_easy_setopt(curlEasy, CURLOPT_PROXYTYPE, CURLPROXY_SOCKS5); break; case URL_PROTOCOL_HTTP: case URL_PROTOCOL_HTTPS: default: - curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); + curl_easy_setopt(curlEasy, CURLOPT_PROXYTYPE, CURLPROXY_HTTP); break; } - curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXYPORT, (long) pi.autodetect_port); - curlErr = curl_easy_setopt(curlEasy, CURLOPT_PROXY, (char*) pi.autodetect_server_name); + curl_easy_setopt(curlEasy, CURLOPT_PROXYPORT, (long) pi.autodetect_port); + curl_easy_setopt(curlEasy, CURLOPT_PROXY, (char*) pi.autodetect_server_name); } } @@ -886,8 +885,7 @@ void HTTP_OP::close_file() { } void HTTP_OP_SET::get_fdset(FDSET_GROUP& fg) { - CURLMcode curlMErr; - curlMErr = curl_multi_fdset( + curl_multi_fdset( g_curlMulti, &fg.read_fds, &fg.write_fds, &fg.exc_fds, &fg.max_fd ); } @@ -896,17 +894,16 @@ void HTTP_OP_SET::get_fdset(FDSET_GROUP& fg) { // get the response code for this request // void HTTP_OP::handle_messages(CURLMsg *pcurlMsg) { - CURLcode curlErr; int retval; - curlErr = curl_easy_getinfo(curlEasy, + curl_easy_getinfo(curlEasy, CURLINFO_RESPONSE_CODE, &response ); // CURLINFO_LONG+25 is a workaround for a bug in the gcc version // included with Mac OS X 10.3.9 // - curlErr = curl_easy_getinfo(curlEasy, + curl_easy_getinfo(curlEasy, (CURLINFO)(CURLINFO_LONG+25) /*CURLINFO_OS_ERRNO*/, &connect_error ); @@ -922,13 +919,9 @@ void HTTP_OP::handle_messages(CURLMsg *pcurlMsg) { // (we don't use it) // double size_download, total_time, starttransfer_time; - curlErr = curl_easy_getinfo(curlEasy, - CURLINFO_SIZE_DOWNLOAD, &size_download - ); - curlErr = curl_easy_getinfo(curlEasy, - CURLINFO_TOTAL_TIME, &total_time - ); - curlErr = curl_easy_getinfo(curlEasy, + curl_easy_getinfo(curlEasy, CURLINFO_SIZE_DOWNLOAD, &size_download); + curl_easy_getinfo(curlEasy, CURLINFO_TOTAL_TIME, &total_time); + curl_easy_getinfo(curlEasy, CURLINFO_STARTTRANSFER_TIME, &starttransfer_time ); double dt = total_time - starttransfer_time; @@ -938,13 +931,9 @@ void HTTP_OP::handle_messages(CURLMsg *pcurlMsg) { } if (want_upload) { double size_upload, total_time, starttransfer_time; - curlErr = curl_easy_getinfo(curlEasy, - CURLINFO_SIZE_UPLOAD, &size_upload - ); - curlErr = curl_easy_getinfo(curlEasy, - CURLINFO_TOTAL_TIME, &total_time - ); - curlErr = curl_easy_getinfo(curlEasy, + curl_easy_getinfo(curlEasy, CURLINFO_SIZE_UPLOAD, &size_upload); + curl_easy_getinfo(curlEasy, CURLINFO_TOTAL_TIME, &total_time); + curl_easy_getinfo(curlEasy, CURLINFO_STARTTRANSFER_TIME, &starttransfer_time ); double dt = total_time - starttransfer_time; diff --git a/client/log_flags.cpp b/client/log_flags.cpp index dab25d98a7..5e64575bf4 100644 --- a/client/log_flags.cpp +++ b/client/log_flags.cpp @@ -297,7 +297,7 @@ int CONFIG::parse_options_client(XML_PARSER& xp) { if (xp.parse_bool(tag, "os_random_only", os_random_only)) continue; #ifndef SIM if (!strcmp(tag, "proxy_info")) { - int retval = config_proxy_info.parse_config(*xp.f); + retval = config_proxy_info.parse_config(*xp.f); if (retval) return retval; continue; } diff --git a/client/net_stats.cpp b/client/net_stats.cpp index 6b1232347f..0f8bfc3697 100644 --- a/client/net_stats.cpp +++ b/client/net_stats.cpp @@ -234,9 +234,7 @@ int LOOKUP_WEBSITE_OP::do_rpc(string& url) { "Project communication failed: attempting access to reference site" ); } - retval = gui_http->do_rpc( - this, (char*)url.c_str(), LOOKUP_WEBSITE_FILENAME, true - ); + retval = gui_http->do_rpc(this, url.c_str(), LOOKUP_WEBSITE_FILENAME, true); if (retval) { error_num = retval; net_status.need_physical_connection = true; diff --git a/client/rr_sim.cpp b/client/rr_sim.cpp index 3757d1dd5d..c99080430d 100644 --- a/client/rr_sim.cpp +++ b/client/rr_sim.cpp @@ -251,7 +251,7 @@ void CLIENT_STATE::rr_simulation() { PROJECT* p, *pbest; RESULT* rp, *rpbest; RR_SIM_STATUS sim_status; - unsigned int i; + unsigned int u; double ar = available_ram(); @@ -265,8 +265,8 @@ void CLIENT_STATE::rr_simulation() { ); } - for (i=0; inon_cpu_intensive) continue; p->rr_sim_status.clear(); } @@ -275,8 +275,8 @@ void CLIENT_STATE::rr_simulation() { // and pick the ones that are initially running. // NOTE: "results" is sorted by increasing arrival time // - for (i=0; irr_sim_misses_deadline = false; if (!rp->nearly_runnable()) continue; if (rp->some_download_stalled()) continue; @@ -331,8 +331,8 @@ void CLIENT_STATE::rr_simulation() { // compute finish times and see which result finishes first // rpbest = NULL; - for (i=0; irrsim_finish_delay = rp->avp->temp_dcf*rp->rrsim_flops_left/rp->rrsim_flops; rp->rrsim_finish_delay = rp->rrsim_flops_left/rp->rrsim_flops; @@ -430,7 +430,7 @@ void CLIENT_STATE::rr_simulation() { while (1) { if (rsc_work_fetch[rt].sim_nused >= coprocs.coprocs[rt].count) break; if (!rsc_work_fetch[rt].pending.size()) break; - RESULT* rp = rsc_work_fetch[rt].pending[0]; + rp = rsc_work_fetch[rt].pending[0]; rsc_work_fetch[rt].pending.erase(rsc_work_fetch[rt].pending.begin()); sim_status.activate(rp, sim_now-now); pbest->rr_sim_status.activate(rp); @@ -438,7 +438,7 @@ void CLIENT_STATE::rr_simulation() { } else { while (1) { if (pbest->rsc_pwf[0].sim_nused >= ncpus) break; - RESULT* rp = pbest->rr_sim_status.get_pending(); + rp = pbest->rr_sim_status.get_pending(); if (!rp) break; sim_status.activate(rp, sim_now-now); pbest->rr_sim_status.activate(rp); diff --git a/client/time_stats.cpp b/client/time_stats.cpp index fd593ab2fe..203bfe3d58 100644 --- a/client/time_stats.cpp +++ b/client/time_stats.cpp @@ -149,11 +149,11 @@ void TIME_STATS::get_log_after(double t, MIOFILE& mf) { // so these get written to disk only when other activities // cause this to happen. Maybe should change this. // -void TIME_STATS::update(int suspend_reason, int gpu_suspend_reason) { +void TIME_STATS::update(int suspend_reason, int _gpu_suspend_reason) { double dt, w1, w2; bool is_active = !(suspend_reason & ~SUSPEND_REASON_CPU_THROTTLE); - bool is_gpu_active = is_active && !gpu_suspend_reason; + bool is_gpu_active = is_active && !_gpu_suspend_reason; if (last_update == 0) { // this is the first time this client has executed. // Assume that everything is active diff --git a/client/work_fetch.cpp b/client/work_fetch.cpp index e91534c779..2f2d915e0e 100644 --- a/client/work_fetch.cpp +++ b/client/work_fetch.cpp @@ -1066,7 +1066,6 @@ void WORK_FETCH::write_request(FILE* f, PROJECT* p) { void WORK_FETCH::handle_reply( PROJECT* p, SCHEDULER_REPLY*, vector new_results ) { - unsigned int i; bool got_rsc[MAX_RSC]; for (int i=0; iavp->gpu_usage.rsc_type] = true; } diff --git a/lib/cc_config.cpp b/lib/cc_config.cpp index f96305955c..38183396be 100644 --- a/lib/cc_config.cpp +++ b/lib/cc_config.cpp @@ -336,7 +336,7 @@ int CONFIG::parse_options(XML_PARSER& xp) { if (xp.parse_bool(tag, "os_random_only", os_random_only)) continue; #ifndef SIM if (!strcmp(tag, "proxy_info")) { - int retval = proxy_info.parse_config(*xp.f); + retval = proxy_info.parse_config(*xp.f); if (retval) return retval; continue; } diff --git a/samples/example_app/Makefile b/samples/example_app/Makefile index a083d47c94..7c161344fc 100644 --- a/samples/example_app/Makefile +++ b/samples/example_app/Makefile @@ -5,6 +5,7 @@ BOINC_API_DIR = $(BOINC_DIR)/api BOINC_LIB_DIR = $(BOINC_DIR)/lib CXXFLAGS = -g \ + -Wall -W -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -fno-common \ -DAPP_GRAPHICS \ -I$(BOINC_DIR) \ -I$(BOINC_LIB_DIR) \ diff --git a/samples/example_app/uc2.cpp b/samples/example_app/uc2.cpp index 320adad20d..6357e06de0 100644 --- a/samples/example_app/uc2.cpp +++ b/samples/example_app/uc2.cpp @@ -216,7 +216,7 @@ int main(int argc, char **argv) { // main loop - read characters, convert to UC, write // - for (int i=0; ; i++) { + for (i=0; ; i++) { c = fgetc(infile); if (c == EOF) break; @@ -267,7 +267,7 @@ int main(int argc, char **argv) { // if (cpu_time) { double start = dtime(); - for (int i=0; ; i++) { + for (i=0; ; i++) { double e = dtime()-start; if (e > cpu_time) break; fd = .5 + .5*(e/cpu_time); diff --git a/samples/vboxwrapper/Makefile b/samples/vboxwrapper/Makefile index 44ff9622e6..e0b533bdd1 100644 --- a/samples/vboxwrapper/Makefile +++ b/samples/vboxwrapper/Makefile @@ -6,6 +6,7 @@ BOINC_API_DIR = $(BOINC_DIR)/api BOINC_LIB_DIR = $(BOINC_DIR)/lib CXXFLAGS = -g \ + -Wall -W -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -fno-common \ -I$(BOINC_DIR) \ -I$(BOINC_LIB_DIR) \ -I$(BOINC_API_DIR) \ diff --git a/samples/vboxwrapper/vbox.cpp b/samples/vboxwrapper/vbox.cpp index e36fce3947..6b008665ab 100644 --- a/samples/vboxwrapper/vbox.cpp +++ b/samples/vboxwrapper/vbox.cpp @@ -1,804 +1,806 @@ -// This file is part of BOINC. -// http://boinc.berkeley.edu -// Copyright (C) 2010 University of California -// -// BOINC is free software; you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License -// as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// BOINC is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with BOINC. If not, see . - -#ifdef _WIN32 -#include "boinc_win.h" -#include "win_util.h" -#else -#include -#include -#include -#include -#include -#include -#include -#include -#endif - -using std::string; - -#if defined(_MSC_VER) || defined(__MINGW32__) -#define popen _popen -#define pclose _pclose -#define getcwd _getcwd -#define putenv _putenv -#endif - -#include "diagnostics.h" -#include "filesys.h" -#include "parse.h" -#include "str_util.h" -#include "str_replace.h" -#include "util.h" -#include "error_numbers.h" -#include "procinfo.h" -#include "boinc_api.h" -#include "vbox.h" -#include "vm.h" - - -// Execute the vbox manage application and copy the output to the -// designated buffer. -// -int virtualbox_vbm_popen(string& arguments, string& output) { - char buf[256]; - string command; - - // Initialize command line - command = "VBoxManage -q " + arguments; - -#ifdef _WIN32 - STARTUPINFO si; - PROCESS_INFORMATION pi; - SECURITY_ATTRIBUTES sa; - SECURITY_DESCRIPTOR sd; - HANDLE hReadPipe, hWritePipe; - void* pBuf; - DWORD dwCount; - unsigned long ulExitCode = 0; - int retval = VBOX_POPEN_ERROR; - - - memset(&si, 0, sizeof(si)); - memset(&pi, 0, sizeof(pi)); - memset(&sa, 0, sizeof(sa)); - memset(&sd, 0, sizeof(sd)); - - - InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); - SetSecurityDescriptorDacl(&sd, true, NULL, false); - - sa.nLength = sizeof(SECURITY_ATTRIBUTES); - sa.bInheritHandle = TRUE; - sa.lpSecurityDescriptor = &sd; - - - if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, 0)) { - fprintf( - stderr, - "%s CreatePipe failed! (%d).\n", - boinc_msg_prefix(buf, sizeof(buf)), - GetLastError() - ); - goto CLEANUP; - } - SetHandleInformation(hReadPipe, HANDLE_FLAG_INHERIT, 0); - - - si.cb = sizeof(STARTUPINFO); - si.dwFlags |= STARTF_FORCEOFFFEEDBACK | STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; - si.wShowWindow = SW_HIDE; - si.hStdOutput = hWritePipe; - si.hStdError = hWritePipe; - si.hStdInput = NULL; - - - // Execute command - if (!CreateProcess(NULL, (LPTSTR)command.c_str(), NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) { - fprintf( - stderr, - "%s CreateProcess failed! (%d).\n", - boinc_msg_prefix(buf, sizeof(buf)), - GetLastError() - ); - goto CLEANUP; - } - - - // Wait until process has completed - while(1) { - GetExitCodeProcess(pi.hProcess, &ulExitCode); - if (ulExitCode != STILL_ACTIVE) break; - } - - - // Copy stdout/stderr to output buffer - if (!PeekNamedPipe(hReadPipe, NULL, NULL, NULL, &dwCount, NULL)) { - fprintf( - stderr, - "%s PeekNamedPipe failed! (%d).\n", - boinc_msg_prefix(buf, sizeof(buf)), - GetLastError() - ); - } - - if (dwCount) { - pBuf = malloc(dwCount+1); - memset(pBuf, 0, dwCount+1); - - if (ReadFile(hReadPipe, pBuf, dwCount, &dwCount, NULL)) { - output += (char*)pBuf; - } - - free(pBuf); - } - - -CLEANUP: - if (pi.hThread) CloseHandle(pi.hThread); - if (pi.hProcess) CloseHandle(pi.hProcess); - if (hReadPipe) CloseHandle(hReadPipe); - if (hWritePipe) CloseHandle(hWritePipe); - - if ((ulExitCode == 0) && (pi.hProcess)) { - retval = VBOX_SUCCESS; - } - - return retval; - -#else - FILE* fp; - - // Execute command - fp = popen(command.c_str(), "r"); - if (fp == NULL){ - fprintf( - stderr, - "%s vbm_popen popen failed! errno = %d\n", - boinc_msg_prefix(buf, sizeof(buf)), - errno - ); - return VBOX_POPEN_ERROR; - } - - // Copy output to buffer - while (fgets(buf, 256, fp)) { - output += buf; - } - - // Close stream - pclose(fp); - -#endif - - return VBOX_SUCCESS; -} - - -// Returns the current directory in which the executable resides. -// -int virtualbox_generate_vm_root_dir( string& dir ) { - char root_dir[256]; - - getcwd(root_dir, (sizeof(root_dir)*sizeof(char))); - dir = root_dir; - - if (!dir.empty()) { - return 1; - } - return 0; -} - - -// Generate a unique virtual machine name for a given task instance -// Rules: -// 1. Must be unique -// 2. Must identifity itself as being part of BOINC -// 3. Must be file system compatible -// -int virtualbox_generate_vm_name( string& name ) { - APP_INIT_DATA aid; - boinc_get_init_data_p( &aid ); - - name.empty(); - name = "boinc_"; - - if (boinc_is_standalone()) { - name += "standalone"; - } else { - name += aid.wu_name; - } - - if (!name.empty()) { - return 1; - } - return 0; -} - - -bool virtualbox_vm_is_registered() { - string command; - string output; - string virtual_machine_name; - - virtualbox_generate_vm_name(virtual_machine_name); - command = "showvminfo " + virtual_machine_name; - - if (VBOX_SUCCESS == virtualbox_vbm_popen(command, output)) { - if (output.find("VBOX_E_OBJECT_NOT_FOUND") != string::npos) { - return true; - } - } - return false; -} - - -bool virtualbox_vm_is_hdd_registered() { - string command; - string output; - string virtual_machine_root_dir; - - virtualbox_generate_vm_root_dir(virtual_machine_root_dir); - - command = "showhdinfo \"" + virtual_machine_root_dir + "/" + vm.image_filename + "\" "; - - if (VBOX_SUCCESS == virtualbox_vbm_popen(command, output)) { - if (output.find("VBOX_E_FILE_ERROR") != string::npos) { - return true; - } - } - return false; -} - - -bool virtualbox_vm_is_running() { - string command; - string output; - string virtual_machine_name; - - virtualbox_generate_vm_name(virtual_machine_name); - command = "list runningvms"; - - if (VBOX_SUCCESS == virtualbox_vbm_popen(command, output)) { - if (output.find(virtual_machine_name) != string::npos) { - return true; - } - } - - return false; -} - -int virtualbox_get_install_directory( string& virtualbox_install_directory ) { -#ifdef _WIN32 - LONG lReturnValue; - HKEY hkSetupHive; - LPTSTR lpszRegistryValue = NULL; - DWORD dwSize = 0; - - // change the current directory to the boinc data directory if it exists - lReturnValue = RegOpenKeyEx( - HKEY_LOCAL_MACHINE, - _T("SOFTWARE\\Oracle\\VirtualBox"), - 0, - KEY_READ, - &hkSetupHive - ); - if (lReturnValue == ERROR_SUCCESS) { - // How large does our buffer need to be? - lReturnValue = RegQueryValueEx( - hkSetupHive, - _T("InstallDir"), - NULL, - NULL, - NULL, - &dwSize - ); - if (lReturnValue != ERROR_FILE_NOT_FOUND) { - // Allocate the buffer space. - lpszRegistryValue = (LPTSTR) malloc(dwSize); - (*lpszRegistryValue) = NULL; - - // Now get the data - lReturnValue = RegQueryValueEx( - hkSetupHive, - _T("InstallDir"), - NULL, - NULL, - (LPBYTE)lpszRegistryValue, - &dwSize - ); - - virtualbox_install_directory = lpszRegistryValue; - } - } - - if (hkSetupHive) RegCloseKey(hkSetupHive); - if (lpszRegistryValue) free(lpszRegistryValue); -#endif - return VBOX_SUCCESS; -} - - -int virtualbox_initialize() { - string virtualbox_install_directory; - string old_path; - string new_path; - char buf[256]; - - virtualbox_get_install_directory(virtualbox_install_directory); - - // Prep the environment so we can execute the vboxmanage application - if (!virtualbox_install_directory.empty()) { - old_path = getenv("path"); - - new_path = "path="; - - new_path += virtualbox_install_directory; - - // Path environment variable seperator -#ifdef _WIN32 - new_path += ";"; -#else - new_path += ":"; -#endif - - new_path += old_path; - - if (putenv((char*)new_path.c_str())) { - fprintf( - stderr, - "%s Failed to modify the search path.\n", - boinc_msg_prefix(buf, sizeof(buf)) - ); - } - } - - return VBOX_SUCCESS; -} - - -int virtualbox_register_vm() { - string command; - string output; - string virtual_machine_name; - string virtual_machine_root_dir; - char buf[256]; - int retval; - - virtualbox_generate_vm_name(virtual_machine_name); - virtualbox_generate_vm_root_dir(virtual_machine_root_dir); - - fprintf( - stderr, - "%s Registering virtual machine. (%s) \n", - boinc_msg_prefix(buf, sizeof(buf)), - virtual_machine_name.c_str() - ); - - - // Create and register the VM - // - command = "createvm "; - command += "--name \"" + virtual_machine_name + "\" "; - command += "--basefolder \"" + virtual_machine_root_dir + "\" "; - command += "--ostype \"" + vm.os_name + "\" "; - command += "--register"; - - retval = virtualbox_vbm_popen(command, output); - if (retval) { - fprintf( - stderr, - "%s Error registering virtual machine! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", - boinc_msg_prefix(buf, sizeof(buf)), - retval, - command.c_str(), - output.c_str() - ); - return retval; - } - - - // Tweak the VM from it's default configuration - // - command = "modifyvm \"" + virtual_machine_name + "\" "; - command += "--memory " + vm.memory_size_mb + " "; - command += "--acpi on "; - command += "--ioapic on "; - command += "--boot1 disk "; - command += "--boot2 none "; - command += "--boot3 none "; - command += "--boot4 none "; - command += "--nic1 nat "; - command += "--natdnsproxy1 on "; - command += "--cableconnected1 off "; - - retval = virtualbox_vbm_popen(command, output); - if (retval) { - fprintf( - stderr, - "%s Error modifing virtual machine! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", - boinc_msg_prefix(buf, sizeof(buf)), - retval, - command.c_str(), - output.c_str() - ); - return retval; - } - - - // Add storage controller to VM - // - command = "storagectl \"" + virtual_machine_name + "\" "; - command += "--name \"IDE Controller\" "; - command += "--add ide "; - command += "--controller PIIX4 "; - - retval = virtualbox_vbm_popen(command, output); - if (retval) { - fprintf( - stderr, - "%s Error adding storage controller to virtual machine! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", - boinc_msg_prefix(buf, sizeof(buf)), - retval, - command.c_str(), - output.c_str() - ); - return retval; - } - - - // Adding virtual hard drive to VM - // - command = "storageattach \"" + virtual_machine_name + "\" "; - command += "--storagectl \"IDE Controller\" "; - command += "--port 0 "; - command += "--device 0 "; - command += "--type hdd "; - command += "--medium \"" + virtual_machine_root_dir + "/" + vm.image_filename + "\" "; - - retval = virtualbox_vbm_popen(command, output); - if (retval) { - fprintf( - stderr, - "%s Error adding virtual disk drive to virtual machine! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", - boinc_msg_prefix(buf, sizeof(buf)), - retval, - command.c_str(), - output.c_str() - ); - return retval; - } - - - // Enable the network adapter if a network connection is required. - // NOTE: Network access should never be allowed if the code running in a - // shared directory or the VM itself is NOT signed. Doing so opens up - // the network behind the firewall to attack. - // - if (vm.enable_network) { - command = "modifyvm \"" + virtual_machine_name + "\" "; - command += "--cableconnected1 on "; - - retval = virtualbox_vbm_popen(command, output); - if (retval) { - fprintf( - stderr, - "%s Error enabling network access for virtual machine! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", - boinc_msg_prefix(buf, sizeof(buf)), - retval, - command.c_str(), - output.c_str() - ); - return retval; - } - } - - - // Enable the shared folder if a shared folder is specified. - // - if (vm.enable_shared_directory) { - command = "sharedfolder add \"" + virtual_machine_name + "\" "; - command += "--name \"shared\" "; - command += "--hostpath \"" + virtual_machine_root_dir + "/shared\""; - - retval = virtualbox_vbm_popen(command, output); - if (retval) { - fprintf( - stderr, - "%s Error enabling shared directory for virtual machine! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", - boinc_msg_prefix(buf, sizeof(buf)), - retval, - command.c_str(), - output.c_str() - ); - return retval; - } - } - - return VBOX_SUCCESS; -} - - -int virtualbox_deregister_vm_by_name( string& virtual_machine_name ) { - string command; - string output; - string virtual_machine_root_dir; - char buf[256]; - int retval; - - virtualbox_generate_vm_root_dir(virtual_machine_root_dir); - - fprintf( - stderr, - "%s Deregistering virtual machine. (%s)\n", - boinc_msg_prefix(buf, sizeof(buf)), - virtual_machine_name.c_str() - ); - - - // First step in deregistering a VM is to delete its storage controller - // - command = "storagectl \"" + virtual_machine_name + "\" "; - command += "--name \"IDE Controller\" "; - command += "--remove "; - - retval = virtualbox_vbm_popen(command, output); - if (retval) { - fprintf( - stderr, - "%s Error removing storage controller from virtual machine! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", - boinc_msg_prefix(buf, sizeof(buf)), - retval, - command.c_str(), - output.c_str() - ); - return retval; - } - - - // Next delete VM - // - command = "unregistervm \"" + virtual_machine_name + "\" "; - command += "--delete "; - - retval = virtualbox_vbm_popen(command, output); - if (retval) { - fprintf( - stderr, - "%s Error removing virtual machine from virtual box! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", - boinc_msg_prefix(buf, sizeof(buf)), - retval, - command.c_str(), - output.c_str() - ); - return retval; - } - - - // Lastly delete medium from Virtual Box Media Registry - // - command = "closemedium disk \"" + virtual_machine_root_dir + "/" + vm.image_filename + "\" "; - - retval = virtualbox_vbm_popen(command, output); - if (retval) { - fprintf( - stderr, - "%s Error removing virtual hdd from virtual box! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", - boinc_msg_prefix(buf, sizeof(buf)), - retval, - command.c_str(), - output.c_str() - ); - return retval; - } - - return VBOX_SUCCESS; -} - - -int virtualbox_deregister_stale_vm() { - string command; - string output; - string virtual_machine_root_dir; - string virtual_machine_name; - size_t uuid_location; - size_t uuid_length; - char buf[256]; - int retval; - - virtualbox_generate_vm_root_dir(virtual_machine_root_dir); - - // We need to determine what the name or uuid is of the previous VM which owns - // this virtual disk - // - command = "showhdinfo \"" + virtual_machine_root_dir + "/" + vm.image_filename + "\" "; - - retval = virtualbox_vbm_popen(command, output); - if (retval) { - fprintf( - stderr, - "%s Error retrieving virtual hard disk information from virtual box! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", - boinc_msg_prefix(buf, sizeof(buf)), - retval, - command.c_str(), - output.c_str() - ); - return retval; - } - - - // Output should look a little like this: - // UUID: c119acaf-636c-41f6-86c9-38e639a31339 - // Accessible: yes - // Logical size: 10240 MBytes - // Current size on disk: 0 MBytes - // Type: normal (base) - // Storage format: VDI - // Format variant: dynamic default - // In use by VMs: test2 (UUID: 000ab2be-1254-4c6a-9fdc-1536a478f601) - // Location: C:\Users\romw\VirtualBox VMs\test2\test2.vdi - // - uuid_location = output.find("(UUID: "); - if (uuid_location != string::npos) { - // We can parse the virtual machine ID from the output - - uuid_location += 7; - uuid_length = output.find(")", uuid_location); - - virtual_machine_name = output.substr(uuid_location, uuid_length); - - // Deregister stale VM by UUID - return virtualbox_deregister_vm_by_name(virtual_machine_name); - } else { - // Did the user delete the VM in VirtualBox and not the medium? If so, - // just remove the medium. - command = "closemedium \"" + virtual_machine_root_dir + "/" + vm.image_filename + "\" "; - - retval = virtualbox_vbm_popen(command, output); - if (retval) { - fprintf( - stderr, - "%s Error removing virtual hdd from virtual box! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", - boinc_msg_prefix(buf, sizeof(buf)), - retval, - command.c_str(), - output.c_str() - ); - return retval; - } - } - - return VBOX_SUCCESS; -} - - -int virtualbox_deregister_vm() { - string virtual_machine_name; - virtualbox_generate_vm_name(virtual_machine_name); - return virtualbox_deregister_vm_by_name(virtual_machine_name); -} - - -int virtualbox_cleanup() { - return VBOX_SUCCESS; -} - - -int virtualbox_startvm() { - string command; - string output; - string virtual_machine_name; - char buf[256]; - int retval; - - virtualbox_generate_vm_name(virtual_machine_name); - command = "startvm \"" + virtual_machine_name + "\" --type headless"; - retval = virtualbox_vbm_popen(command, output); - if (retval) { - fprintf( - stderr, - "%s Error starting virtual machine! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", - boinc_msg_prefix(buf, sizeof(buf)), - retval, - command.c_str(), - output.c_str() - ); - return retval; - } - return VBOX_SUCCESS; -} - - -int virtualbox_stopvm() { - string command; - string output; - string virtual_machine_name; - char buf[256]; - int retval; - - virtualbox_generate_vm_name(virtual_machine_name); - command = "controlvm \"" + virtual_machine_name + "\" savestate"; - retval = virtualbox_vbm_popen(command, output); - if (retval) { - fprintf( - stderr, - "%s Error stopping virtual machine! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", - boinc_msg_prefix(buf, sizeof(buf)), - retval, - command.c_str(), - output.c_str() - ); - return retval; - } - return VBOX_SUCCESS; -} - - -int virtualbox_pausevm() { - string command; - string output; - string virtual_machine_name; - char buf[256]; - int retval; - - virtualbox_generate_vm_name(virtual_machine_name); - command = "controlvm \"" + virtual_machine_name + "\" pause"; - retval = virtualbox_vbm_popen(command, output); - if (retval) { - fprintf( - stderr, - "%s Error pausing virtual machine! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", - boinc_msg_prefix(buf, sizeof(buf)), - retval, - command.c_str(), - output.c_str() - ); - return retval; - } - return VBOX_SUCCESS; -} - - -int virtualbox_resumevm() { - string command; - string output; - string virtual_machine_name; - char buf[256]; - int retval; - - virtualbox_generate_vm_name(virtual_machine_name); - command = "controlvm \"" + virtual_machine_name + "\" resume"; - retval = virtualbox_vbm_popen(command, output); - if (retval) { - fprintf( - stderr, - "%s Error resuming virtual machine! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", - boinc_msg_prefix(buf, sizeof(buf)), - retval, - command.c_str(), - output.c_str() - ); - return retval; - } - return VBOX_SUCCESS; -} - - -int virtualbox_monitor() { - return VBOX_SUCCESS; -} - +// This file is part of BOINC. +// http://boinc.berkeley.edu +// Copyright (C) 2010 University of California +// +// BOINC is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// BOINC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with BOINC. If not, see . + +#ifdef _WIN32 +#include "boinc_win.h" +#include "win_util.h" +#else +#include +#include +#include +#include +#include +#include +#include +#include +#endif + +using std::string; + +#if defined(_MSC_VER) || defined(__MINGW32__) +#define popen _popen +#define pclose _pclose +#define getcwd _getcwd +#define putenv _putenv +#endif + +#include "diagnostics.h" +#include "filesys.h" +#include "parse.h" +#include "str_util.h" +#include "str_replace.h" +#include "util.h" +#include "error_numbers.h" +#include "procinfo.h" +#include "boinc_api.h" +#include "vbox.h" +#include "vm.h" + + +// Execute the vbox manage application and copy the output to the +// designated buffer. +// +int virtualbox_vbm_popen(string& arguments, string& output) { + char buf[256]; + string command; + + // Initialize command line + command = "VBoxManage -q " + arguments; + +#ifdef _WIN32 + STARTUPINFO si; + PROCESS_INFORMATION pi; + SECURITY_ATTRIBUTES sa; + SECURITY_DESCRIPTOR sd; + HANDLE hReadPipe, hWritePipe; + void* pBuf; + DWORD dwCount; + unsigned long ulExitCode = 0; + int retval = VBOX_POPEN_ERROR; + + + memset(&si, 0, sizeof(si)); + memset(&pi, 0, sizeof(pi)); + memset(&sa, 0, sizeof(sa)); + memset(&sd, 0, sizeof(sd)); + + + InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION); + SetSecurityDescriptorDacl(&sd, true, NULL, false); + + sa.nLength = sizeof(SECURITY_ATTRIBUTES); + sa.bInheritHandle = TRUE; + sa.lpSecurityDescriptor = &sd; + + + if (!CreatePipe(&hReadPipe, &hWritePipe, &sa, 0)) { + fprintf( + stderr, + "%s CreatePipe failed! (%d).\n", + boinc_msg_prefix(buf, sizeof(buf)), + GetLastError() + ); + goto CLEANUP; + } + SetHandleInformation(hReadPipe, HANDLE_FLAG_INHERIT, 0); + + + si.cb = sizeof(STARTUPINFO); + si.dwFlags |= STARTF_FORCEOFFFEEDBACK | STARTF_USESHOWWINDOW | STARTF_USESTDHANDLES; + si.wShowWindow = SW_HIDE; + si.hStdOutput = hWritePipe; + si.hStdError = hWritePipe; + si.hStdInput = NULL; + + + // Execute command + if (!CreateProcess(NULL, (LPTSTR)command.c_str(), NULL, NULL, TRUE, CREATE_NO_WINDOW, NULL, NULL, &si, &pi)) { + fprintf( + stderr, + "%s CreateProcess failed! (%d).\n", + boinc_msg_prefix(buf, sizeof(buf)), + GetLastError() + ); + goto CLEANUP; + } + + + // Wait until process has completed + while(1) { + GetExitCodeProcess(pi.hProcess, &ulExitCode); + if (ulExitCode != STILL_ACTIVE) break; + } + + + // Copy stdout/stderr to output buffer + if (!PeekNamedPipe(hReadPipe, NULL, NULL, NULL, &dwCount, NULL)) { + fprintf( + stderr, + "%s PeekNamedPipe failed! (%d).\n", + boinc_msg_prefix(buf, sizeof(buf)), + GetLastError() + ); + } + + if (dwCount) { + pBuf = malloc(dwCount+1); + memset(pBuf, 0, dwCount+1); + + if (ReadFile(hReadPipe, pBuf, dwCount, &dwCount, NULL)) { + output += (char*)pBuf; + } + + free(pBuf); + } + + +CLEANUP: + if (pi.hThread) CloseHandle(pi.hThread); + if (pi.hProcess) CloseHandle(pi.hProcess); + if (hReadPipe) CloseHandle(hReadPipe); + if (hWritePipe) CloseHandle(hWritePipe); + + if ((ulExitCode == 0) && (pi.hProcess)) { + retval = VBOX_SUCCESS; + } + + return retval; + +#else + FILE* fp; + + // Execute command + fp = popen(command.c_str(), "r"); + if (fp == NULL){ + fprintf( + stderr, + "%s vbm_popen popen failed! errno = %d\n", + boinc_msg_prefix(buf, sizeof(buf)), + errno + ); + return VBOX_POPEN_ERROR; + } + + // Copy output to buffer + while (fgets(buf, 256, fp)) { + output += buf; + } + + // Close stream + pclose(fp); + +#endif + + return VBOX_SUCCESS; +} + + +// Returns the current directory in which the executable resides. +// +int virtualbox_generate_vm_root_dir( string& dir ) { + char root_dir[256]; + + getcwd(root_dir, (sizeof(root_dir)*sizeof(char))); + dir = root_dir; + + if (!dir.empty()) { + return 1; + } + return 0; +} + + +// Generate a unique virtual machine name for a given task instance +// Rules: +// 1. Must be unique +// 2. Must identifity itself as being part of BOINC +// 3. Must be file system compatible +// +int virtualbox_generate_vm_name( string& name ) { + APP_INIT_DATA aid; + boinc_get_init_data_p( &aid ); + + name.empty(); + name = "boinc_"; + + if (boinc_is_standalone()) { + name += "standalone"; + } else { + name += aid.wu_name; + } + + if (!name.empty()) { + return 1; + } + return 0; +} + + +bool virtualbox_vm_is_registered() { + string command; + string output; + string virtual_machine_name; + + virtualbox_generate_vm_name(virtual_machine_name); + command = "showvminfo " + virtual_machine_name; + + if (VBOX_SUCCESS == virtualbox_vbm_popen(command, output)) { + if (output.find("VBOX_E_OBJECT_NOT_FOUND") != string::npos) { + return true; + } + } + return false; +} + + +bool virtualbox_vm_is_hdd_registered() { + string command; + string output; + string virtual_machine_root_dir; + + virtualbox_generate_vm_root_dir(virtual_machine_root_dir); + + command = "showhdinfo \"" + virtual_machine_root_dir + "/" + vm.image_filename + "\" "; + + if (VBOX_SUCCESS == virtualbox_vbm_popen(command, output)) { + if (output.find("VBOX_E_FILE_ERROR") != string::npos) { + return true; + } + } + return false; +} + + +bool virtualbox_vm_is_running() { + string command; + string output; + string virtual_machine_name; + + virtualbox_generate_vm_name(virtual_machine_name); + command = "list runningvms"; + + if (VBOX_SUCCESS == virtualbox_vbm_popen(command, output)) { + if (output.find(virtual_machine_name) != string::npos) { + return true; + } + } + + return false; +} + +int virtualbox_get_install_directory(string& virtualbox_install_directory ) { +#ifdef _WIN32 + LONG lReturnValue; + HKEY hkSetupHive; + LPTSTR lpszRegistryValue = NULL; + DWORD dwSize = 0; + + // change the current directory to the boinc data directory if it exists + lReturnValue = RegOpenKeyEx( + HKEY_LOCAL_MACHINE, + _T("SOFTWARE\\Oracle\\VirtualBox"), + 0, + KEY_READ, + &hkSetupHive + ); + if (lReturnValue == ERROR_SUCCESS) { + // How large does our buffer need to be? + lReturnValue = RegQueryValueEx( + hkSetupHive, + _T("InstallDir"), + NULL, + NULL, + NULL, + &dwSize + ); + if (lReturnValue != ERROR_FILE_NOT_FOUND) { + // Allocate the buffer space. + lpszRegistryValue = (LPTSTR) malloc(dwSize); + (*lpszRegistryValue) = NULL; + + // Now get the data + lReturnValue = RegQueryValueEx( + hkSetupHive, + _T("InstallDir"), + NULL, + NULL, + (LPBYTE)lpszRegistryValue, + &dwSize + ); + + virtualbox_install_directory = lpszRegistryValue; + } + } + + if (hkSetupHive) RegCloseKey(hkSetupHive); + if (lpszRegistryValue) free(lpszRegistryValue); +#else + virtualbox_install_directory = ""; +#endif + return VBOX_SUCCESS; +} + + +int virtualbox_initialize() { + string virtualbox_install_directory; + string old_path; + string new_path; + char buf[256]; + + virtualbox_get_install_directory(virtualbox_install_directory); + + // Prep the environment so we can execute the vboxmanage application + if (!virtualbox_install_directory.empty()) { + old_path = getenv("path"); + + new_path = "path="; + + new_path += virtualbox_install_directory; + + // Path environment variable seperator +#ifdef _WIN32 + new_path += ";"; +#else + new_path += ":"; +#endif + + new_path += old_path; + + if (putenv((char*)new_path.c_str())) { + fprintf( + stderr, + "%s Failed to modify the search path.\n", + boinc_msg_prefix(buf, sizeof(buf)) + ); + } + } + + return VBOX_SUCCESS; +} + + +int virtualbox_register_vm() { + string command; + string output; + string virtual_machine_name; + string virtual_machine_root_dir; + char buf[256]; + int retval; + + virtualbox_generate_vm_name(virtual_machine_name); + virtualbox_generate_vm_root_dir(virtual_machine_root_dir); + + fprintf( + stderr, + "%s Registering virtual machine. (%s) \n", + boinc_msg_prefix(buf, sizeof(buf)), + virtual_machine_name.c_str() + ); + + + // Create and register the VM + // + command = "createvm "; + command += "--name \"" + virtual_machine_name + "\" "; + command += "--basefolder \"" + virtual_machine_root_dir + "\" "; + command += "--ostype \"" + vm.os_name + "\" "; + command += "--register"; + + retval = virtualbox_vbm_popen(command, output); + if (retval) { + fprintf( + stderr, + "%s Error registering virtual machine! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", + boinc_msg_prefix(buf, sizeof(buf)), + retval, + command.c_str(), + output.c_str() + ); + return retval; + } + + + // Tweak the VM from it's default configuration + // + command = "modifyvm \"" + virtual_machine_name + "\" "; + command += "--memory " + vm.memory_size_mb + " "; + command += "--acpi on "; + command += "--ioapic on "; + command += "--boot1 disk "; + command += "--boot2 none "; + command += "--boot3 none "; + command += "--boot4 none "; + command += "--nic1 nat "; + command += "--natdnsproxy1 on "; + command += "--cableconnected1 off "; + + retval = virtualbox_vbm_popen(command, output); + if (retval) { + fprintf( + stderr, + "%s Error modifing virtual machine! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", + boinc_msg_prefix(buf, sizeof(buf)), + retval, + command.c_str(), + output.c_str() + ); + return retval; + } + + + // Add storage controller to VM + // + command = "storagectl \"" + virtual_machine_name + "\" "; + command += "--name \"IDE Controller\" "; + command += "--add ide "; + command += "--controller PIIX4 "; + + retval = virtualbox_vbm_popen(command, output); + if (retval) { + fprintf( + stderr, + "%s Error adding storage controller to virtual machine! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", + boinc_msg_prefix(buf, sizeof(buf)), + retval, + command.c_str(), + output.c_str() + ); + return retval; + } + + + // Adding virtual hard drive to VM + // + command = "storageattach \"" + virtual_machine_name + "\" "; + command += "--storagectl \"IDE Controller\" "; + command += "--port 0 "; + command += "--device 0 "; + command += "--type hdd "; + command += "--medium \"" + virtual_machine_root_dir + "/" + vm.image_filename + "\" "; + + retval = virtualbox_vbm_popen(command, output); + if (retval) { + fprintf( + stderr, + "%s Error adding virtual disk drive to virtual machine! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", + boinc_msg_prefix(buf, sizeof(buf)), + retval, + command.c_str(), + output.c_str() + ); + return retval; + } + + + // Enable the network adapter if a network connection is required. + // NOTE: Network access should never be allowed if the code running in a + // shared directory or the VM itself is NOT signed. Doing so opens up + // the network behind the firewall to attack. + // + if (vm.enable_network) { + command = "modifyvm \"" + virtual_machine_name + "\" "; + command += "--cableconnected1 on "; + + retval = virtualbox_vbm_popen(command, output); + if (retval) { + fprintf( + stderr, + "%s Error enabling network access for virtual machine! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", + boinc_msg_prefix(buf, sizeof(buf)), + retval, + command.c_str(), + output.c_str() + ); + return retval; + } + } + + + // Enable the shared folder if a shared folder is specified. + // + if (vm.enable_shared_directory) { + command = "sharedfolder add \"" + virtual_machine_name + "\" "; + command += "--name \"shared\" "; + command += "--hostpath \"" + virtual_machine_root_dir + "/shared\""; + + retval = virtualbox_vbm_popen(command, output); + if (retval) { + fprintf( + stderr, + "%s Error enabling shared directory for virtual machine! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", + boinc_msg_prefix(buf, sizeof(buf)), + retval, + command.c_str(), + output.c_str() + ); + return retval; + } + } + + return VBOX_SUCCESS; +} + + +int virtualbox_deregister_vm_by_name( string& virtual_machine_name ) { + string command; + string output; + string virtual_machine_root_dir; + char buf[256]; + int retval; + + virtualbox_generate_vm_root_dir(virtual_machine_root_dir); + + fprintf( + stderr, + "%s Deregistering virtual machine. (%s)\n", + boinc_msg_prefix(buf, sizeof(buf)), + virtual_machine_name.c_str() + ); + + + // First step in deregistering a VM is to delete its storage controller + // + command = "storagectl \"" + virtual_machine_name + "\" "; + command += "--name \"IDE Controller\" "; + command += "--remove "; + + retval = virtualbox_vbm_popen(command, output); + if (retval) { + fprintf( + stderr, + "%s Error removing storage controller from virtual machine! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", + boinc_msg_prefix(buf, sizeof(buf)), + retval, + command.c_str(), + output.c_str() + ); + return retval; + } + + + // Next delete VM + // + command = "unregistervm \"" + virtual_machine_name + "\" "; + command += "--delete "; + + retval = virtualbox_vbm_popen(command, output); + if (retval) { + fprintf( + stderr, + "%s Error removing virtual machine from virtual box! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", + boinc_msg_prefix(buf, sizeof(buf)), + retval, + command.c_str(), + output.c_str() + ); + return retval; + } + + + // Lastly delete medium from Virtual Box Media Registry + // + command = "closemedium disk \"" + virtual_machine_root_dir + "/" + vm.image_filename + "\" "; + + retval = virtualbox_vbm_popen(command, output); + if (retval) { + fprintf( + stderr, + "%s Error removing virtual hdd from virtual box! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", + boinc_msg_prefix(buf, sizeof(buf)), + retval, + command.c_str(), + output.c_str() + ); + return retval; + } + + return VBOX_SUCCESS; +} + + +int virtualbox_deregister_stale_vm() { + string command; + string output; + string virtual_machine_root_dir; + string virtual_machine_name; + size_t uuid_location; + size_t uuid_length; + char buf[256]; + int retval; + + virtualbox_generate_vm_root_dir(virtual_machine_root_dir); + + // We need to determine what the name or uuid is of the previous VM which owns + // this virtual disk + // + command = "showhdinfo \"" + virtual_machine_root_dir + "/" + vm.image_filename + "\" "; + + retval = virtualbox_vbm_popen(command, output); + if (retval) { + fprintf( + stderr, + "%s Error retrieving virtual hard disk information from virtual box! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", + boinc_msg_prefix(buf, sizeof(buf)), + retval, + command.c_str(), + output.c_str() + ); + return retval; + } + + + // Output should look a little like this: + // UUID: c119acaf-636c-41f6-86c9-38e639a31339 + // Accessible: yes + // Logical size: 10240 MBytes + // Current size on disk: 0 MBytes + // Type: normal (base) + // Storage format: VDI + // Format variant: dynamic default + // In use by VMs: test2 (UUID: 000ab2be-1254-4c6a-9fdc-1536a478f601) + // Location: C:\Users\romw\VirtualBox VMs\test2\test2.vdi + // + uuid_location = output.find("(UUID: "); + if (uuid_location != string::npos) { + // We can parse the virtual machine ID from the output + + uuid_location += 7; + uuid_length = output.find(")", uuid_location); + + virtual_machine_name = output.substr(uuid_location, uuid_length); + + // Deregister stale VM by UUID + return virtualbox_deregister_vm_by_name(virtual_machine_name); + } else { + // Did the user delete the VM in VirtualBox and not the medium? If so, + // just remove the medium. + command = "closemedium \"" + virtual_machine_root_dir + "/" + vm.image_filename + "\" "; + + retval = virtualbox_vbm_popen(command, output); + if (retval) { + fprintf( + stderr, + "%s Error removing virtual hdd from virtual box! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", + boinc_msg_prefix(buf, sizeof(buf)), + retval, + command.c_str(), + output.c_str() + ); + return retval; + } + } + + return VBOX_SUCCESS; +} + + +int virtualbox_deregister_vm() { + string virtual_machine_name; + virtualbox_generate_vm_name(virtual_machine_name); + return virtualbox_deregister_vm_by_name(virtual_machine_name); +} + + +int virtualbox_cleanup() { + return VBOX_SUCCESS; +} + + +int virtualbox_startvm() { + string command; + string output; + string virtual_machine_name; + char buf[256]; + int retval; + + virtualbox_generate_vm_name(virtual_machine_name); + command = "startvm \"" + virtual_machine_name + "\" --type headless"; + retval = virtualbox_vbm_popen(command, output); + if (retval) { + fprintf( + stderr, + "%s Error starting virtual machine! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", + boinc_msg_prefix(buf, sizeof(buf)), + retval, + command.c_str(), + output.c_str() + ); + return retval; + } + return VBOX_SUCCESS; +} + + +int virtualbox_stopvm() { + string command; + string output; + string virtual_machine_name; + char buf[256]; + int retval; + + virtualbox_generate_vm_name(virtual_machine_name); + command = "controlvm \"" + virtual_machine_name + "\" savestate"; + retval = virtualbox_vbm_popen(command, output); + if (retval) { + fprintf( + stderr, + "%s Error stopping virtual machine! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", + boinc_msg_prefix(buf, sizeof(buf)), + retval, + command.c_str(), + output.c_str() + ); + return retval; + } + return VBOX_SUCCESS; +} + + +int virtualbox_pausevm() { + string command; + string output; + string virtual_machine_name; + char buf[256]; + int retval; + + virtualbox_generate_vm_name(virtual_machine_name); + command = "controlvm \"" + virtual_machine_name + "\" pause"; + retval = virtualbox_vbm_popen(command, output); + if (retval) { + fprintf( + stderr, + "%s Error pausing virtual machine! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", + boinc_msg_prefix(buf, sizeof(buf)), + retval, + command.c_str(), + output.c_str() + ); + return retval; + } + return VBOX_SUCCESS; +} + + +int virtualbox_resumevm() { + string command; + string output; + string virtual_machine_name; + char buf[256]; + int retval; + + virtualbox_generate_vm_name(virtual_machine_name); + command = "controlvm \"" + virtual_machine_name + "\" resume"; + retval = virtualbox_vbm_popen(command, output); + if (retval) { + fprintf( + stderr, + "%s Error resuming virtual machine! rc = 0x%x\nCommand:\n%s\nOutput:\n%s\n", + boinc_msg_prefix(buf, sizeof(buf)), + retval, + command.c_str(), + output.c_str() + ); + return retval; + } + return VBOX_SUCCESS; +} + + +int virtualbox_monitor() { + return VBOX_SUCCESS; +} + diff --git a/samples/vboxwrapper/vboxwrapper.cpp b/samples/vboxwrapper/vboxwrapper.cpp index 5a81f9f74b..43186ddeed 100644 --- a/samples/vboxwrapper/vboxwrapper.cpp +++ b/samples/vboxwrapper/vboxwrapper.cpp @@ -1,216 +1,216 @@ -// This file is part of BOINC. -// http://boinc.berkeley.edu -// Copyright (C) 2010 University of California -// -// BOINC is free software; you can redistribute it and/or modify it -// under the terms of the GNU Lesser General Public License -// as published by the Free Software Foundation, -// either version 3 of the License, or (at your option) any later version. -// -// BOINC is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. -// See the GNU Lesser General Public License for more details. -// -// You should have received a copy of the GNU Lesser General Public License -// along with BOINC. If not, see . - -// vboxwrapper.cpp -// vboxwrapper program - lets you use VirtualBox VMs with BOINC -// -// Handles: -// - suspend/resume/quit/abort -// - reporting CPU time -// - loss of heartbeat from core client -// - checkpointing -// (at the level of task; or potentially within task) -// -// See http://boinc.berkeley.edu/wrapper.php for details -// Contributor: Andrew J. Younge (ajy4490@umiacs.umd.edu) -// Contributor: Jie Wu -// Contributor: Daniel Lombraña González -// - -#ifdef _WIN32 -#include "boinc_win.h" -#include "win_util.h" -#else -#include -#include -#include -#include -#include -#include -#include -#endif - -#include "boinc_api.h" -#include "diagnostics.h" -#include "filesys.h" -#include "parse.h" -#include "str_util.h" -#include "str_replace.h" -#include "util.h" -#include "error_numbers.h" -#include "procinfo.h" -#include "vm.h" -#include "vbox.h" - -#define JOB_FILENAME "vbox_job.xml" -#define CHECKPOINT_FILENAME "vbox_checkpoint.txt" -#define POLL_PERIOD 1.0 - -int parse_job_file() { - MIOFILE mf; - char tag[1024], buf[256], buf2[256]; - bool is_tag; - - boinc_resolve_filename(JOB_FILENAME, buf, 1024); - FILE* f = boinc_fopen(buf, "r"); - if (!f) { - fprintf(stderr, - "%s can't open job file %s\n", - boinc_msg_prefix(buf2, sizeof(buf2)), buf - ); - return ERR_FOPEN; - } - mf.init_file(f); - XML_PARSER xp(&mf); - - if (!xp.parse_start("vbox_job_desc")) return ERR_XML_PARSE; - while (!xp.get(tag, sizeof(tag), is_tag)) { - if (!is_tag) { - fprintf(stderr, - "%s SCHED_CONFIG::parse(): unexpected text %s\n", - boinc_msg_prefix(buf2, sizeof(buf2)), tag - ); - continue; - } - if (!strcmp(tag, "vbox_job_desc")) { - vm.parse(xp); - } - } - fclose(f); - return ERR_XML_PARSE; -} - - -void write_checkpoint(double cpu) { - boinc_begin_critical_section(); - FILE* f = fopen(CHECKPOINT_FILENAME, "w"); - if (!f) return; - fprintf(f, "%f\n", cpu); - fclose(f); - boinc_checkpoint_completed(); -} - - -void read_checkpoint(double& cpu) { - double c; - cpu = 0; - FILE* f = fopen(CHECKPOINT_FILENAME, "r"); - if (!f) return; - int n = fscanf(f, "%lf", &c); - fclose(f); - if (n != 1) return; - cpu = c; -} - - -int main(int argc, char** argv) { - BOINC_OPTIONS boinc_options; - BOINC_STATUS boinc_status; - double current_cpu_time = 0.0; - double checkpoint_cpu_time = 0.0; - bool is_running = false; - char buf[256]; - int retval; - - memset(&boinc_options, 0, sizeof(boinc_options)); - boinc_options.main_program = true; - boinc_options.check_heartbeat = true; - boinc_options.handle_process_control = true; - boinc_init_options(&boinc_options); - - fprintf( - stderr, - "%s vboxwrapper: starting\n", - boinc_msg_prefix(buf, sizeof(buf)) - ); - - retval = parse_job_file(); - if (retval) { - fprintf( - stderr, - "%s can't parse job file: %d\n", - boinc_msg_prefix(buf, sizeof(buf)), - retval - ); - boinc_finish(retval); - } - - read_checkpoint(checkpoint_cpu_time); - - retval = vm.run(); - if (retval) { - boinc_finish(retval); - } - - while (1) { - - vm.poll(); - is_running = vm.is_running(); - - boinc_get_status(&boinc_status); - if (boinc_status.no_heartbeat || boinc_status.quit_request) { - vm.stop(); - write_checkpoint(checkpoint_cpu_time); - boinc_temporary_exit(0); - } - if (boinc_status.abort_request) { - vm.cleanup(); - write_checkpoint(checkpoint_cpu_time); - boinc_finish(EXIT_ABORTED_BY_CLIENT); - } - if (!is_running) { - vm.cleanup(); - write_checkpoint(checkpoint_cpu_time); - boinc_finish(0); - } - if (boinc_status.suspended) { - if (!vm.suspended) { - vm.pause(); - } - } else { - if (vm.suspended) { - vm.resume(); - } - } - if (boinc_time_to_checkpoint()) { - boinc_checkpoint_completed(); - checkpoint_cpu_time += current_cpu_time; - current_cpu_time = 0.0; - } - if (is_running) { - current_cpu_time += 1.0; - boinc_report_app_status(current_cpu_time, checkpoint_cpu_time, 0.0); - } - boinc_sleep(POLL_PERIOD); - } - - return 0; -} - -#ifdef _WIN32 - -int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR Args, int WinMode) { - LPSTR command_line; - char* argv[100]; - int argc; - - command_line = GetCommandLine(); - argc = parse_command_line(command_line, argv); - return main(argc, argv); -} - -#endif +// This file is part of BOINC. +// http://boinc.berkeley.edu +// Copyright (C) 2010 University of California +// +// BOINC is free software; you can redistribute it and/or modify it +// under the terms of the GNU Lesser General Public License +// as published by the Free Software Foundation, +// either version 3 of the License, or (at your option) any later version. +// +// BOINC is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. +// See the GNU Lesser General Public License for more details. +// +// You should have received a copy of the GNU Lesser General Public License +// along with BOINC. If not, see . + +// vboxwrapper.cpp +// vboxwrapper program - lets you use VirtualBox VMs with BOINC +// +// Handles: +// - suspend/resume/quit/abort +// - reporting CPU time +// - loss of heartbeat from core client +// - checkpointing +// (at the level of task; or potentially within task) +// +// See http://boinc.berkeley.edu/wrapper.php for details +// Contributor: Andrew J. Younge (ajy4490@umiacs.umd.edu) +// Contributor: Jie Wu +// Contributor: Daniel Lombraña González +// + +#ifdef _WIN32 +#include "boinc_win.h" +#include "win_util.h" +#else +#include +#include +#include +#include +#include +#include +#include +#endif + +#include "boinc_api.h" +#include "diagnostics.h" +#include "filesys.h" +#include "parse.h" +#include "str_util.h" +#include "str_replace.h" +#include "util.h" +#include "error_numbers.h" +#include "procinfo.h" +#include "vm.h" +#include "vbox.h" + +#define JOB_FILENAME "vbox_job.xml" +#define CHECKPOINT_FILENAME "vbox_checkpoint.txt" +#define POLL_PERIOD 1.0 + +int parse_job_file() { + MIOFILE mf; + char tag[1024], buf[256], buf2[256]; + bool is_tag; + + boinc_resolve_filename(JOB_FILENAME, buf, 1024); + FILE* f = boinc_fopen(buf, "r"); + if (!f) { + fprintf(stderr, + "%s can't open job file %s\n", + boinc_msg_prefix(buf2, sizeof(buf2)), buf + ); + return ERR_FOPEN; + } + mf.init_file(f); + XML_PARSER xp(&mf); + + if (!xp.parse_start("vbox_job_desc")) return ERR_XML_PARSE; + while (!xp.get(tag, sizeof(tag), is_tag)) { + if (!is_tag) { + fprintf(stderr, + "%s SCHED_CONFIG::parse(): unexpected text %s\n", + boinc_msg_prefix(buf2, sizeof(buf2)), tag + ); + continue; + } + if (!strcmp(tag, "vbox_job_desc")) { + vm.parse(xp); + } + } + fclose(f); + return ERR_XML_PARSE; +} + + +void write_checkpoint(double cpu) { + boinc_begin_critical_section(); + FILE* f = fopen(CHECKPOINT_FILENAME, "w"); + if (!f) return; + fprintf(f, "%f\n", cpu); + fclose(f); + boinc_checkpoint_completed(); +} + + +void read_checkpoint(double& cpu) { + double c; + cpu = 0; + FILE* f = fopen(CHECKPOINT_FILENAME, "r"); + if (!f) return; + int n = fscanf(f, "%lf", &c); + fclose(f); + if (n != 1) return; + cpu = c; +} + + +int main() { + BOINC_OPTIONS boinc_options; + BOINC_STATUS boinc_status; + double current_cpu_time = 0.0; + double checkpoint_cpu_time = 0.0; + bool is_running = false; + char buf[256]; + int retval; + + memset(&boinc_options, 0, sizeof(boinc_options)); + boinc_options.main_program = true; + boinc_options.check_heartbeat = true; + boinc_options.handle_process_control = true; + boinc_init_options(&boinc_options); + + fprintf( + stderr, + "%s vboxwrapper: starting\n", + boinc_msg_prefix(buf, sizeof(buf)) + ); + + retval = parse_job_file(); + if (retval) { + fprintf( + stderr, + "%s can't parse job file: %d\n", + boinc_msg_prefix(buf, sizeof(buf)), + retval + ); + boinc_finish(retval); + } + + read_checkpoint(checkpoint_cpu_time); + + retval = vm.run(); + if (retval) { + boinc_finish(retval); + } + + while (1) { + + vm.poll(); + is_running = vm.is_running(); + + boinc_get_status(&boinc_status); + if (boinc_status.no_heartbeat || boinc_status.quit_request) { + vm.stop(); + write_checkpoint(checkpoint_cpu_time); + boinc_temporary_exit(0); + } + if (boinc_status.abort_request) { + vm.cleanup(); + write_checkpoint(checkpoint_cpu_time); + boinc_finish(EXIT_ABORTED_BY_CLIENT); + } + if (!is_running) { + vm.cleanup(); + write_checkpoint(checkpoint_cpu_time); + boinc_finish(0); + } + if (boinc_status.suspended) { + if (!vm.suspended) { + vm.pause(); + } + } else { + if (vm.suspended) { + vm.resume(); + } + } + if (boinc_time_to_checkpoint()) { + boinc_checkpoint_completed(); + checkpoint_cpu_time += current_cpu_time; + current_cpu_time = 0.0; + } + if (is_running) { + current_cpu_time += 1.0; + boinc_report_app_status(current_cpu_time, checkpoint_cpu_time, 0.0); + } + boinc_sleep(POLL_PERIOD); + } + + return 0; +} + +#ifdef _WIN32 + +int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR Args, int WinMode) { + LPSTR command_line; + char* argv[100]; + int argc; + + command_line = GetCommandLine(); + argc = parse_command_line(command_line, argv); + return main(argc, argv); +} + +#endif diff --git a/samples/wrapper/Makefile b/samples/wrapper/Makefile index 8b6f5b2354..01800066ff 100644 --- a/samples/wrapper/Makefile +++ b/samples/wrapper/Makefile @@ -6,6 +6,7 @@ BOINC_API_DIR = $(BOINC_DIR)/api BOINC_LIB_DIR = $(BOINC_DIR)/lib CXXFLAGS = -g \ + -Wall -W -Wshadow -Wpointer-arith -Wcast-qual -Wcast-align -Wwrite-strings -fno-common \ -I$(BOINC_DIR) \ -I$(BOINC_LIB_DIR) \ -I$(BOINC_API_DIR) \ diff --git a/samples/wrapper/wrapper.cpp b/samples/wrapper/wrapper.cpp index afecf1b6fd..cb042c1eee 100644 --- a/samples/wrapper/wrapper.cpp +++ b/samples/wrapper/wrapper.cpp @@ -472,7 +472,6 @@ int TASK::run(int argct, char** argvt) { SetThreadPriority(thread_handle, THREAD_PRIORITY_IDLE); #else int retval, argc; - char progname[256]; char* argv[256]; char arglist[4096]; FILE* stdout_file; @@ -515,12 +514,11 @@ int TASK::run(int argct, char** argvt) { argc = parse_command_line(arglist, argv+1); setpriority(PRIO_PROCESS, 0, PROCESS_IDLE_PRIORITY); if (!exec_dir.empty()) { - int retval = chdir(exec_dir.c_str()); -#if 0 - fprintf(stderr, "%s change to directory for task: %s\n", - retval ? "Failed to" : "Successful", exec_dir.c_str() - ); -#endif + retval = chdir(exec_dir.c_str()); + if (!retval) { + fprintf(stderr, "chdir() to %s failed\n", exec_dir.c_str()); + exit(1); + } } // setup environment variables (if any) @@ -554,7 +552,7 @@ bool TASK::poll(int& status) { } } #else - int wpid, stat; + int wpid; struct rusage ru; wpid = wait4(pid, &status, WNOHANG, &ru); @@ -683,9 +681,9 @@ int main(int argc, char** argv) { double checkpoint_cpu_time; // overall CPU time at last checkpoint - for (int i=1; inapps; i++) { + for (i=0; inapps; i++) { if (!ssp->apps[i].homogeneous_redundancy) { all_apps_use_hr = false; break;