// for each FILE_INFO (i.e. each project file the client knows about) // check that the file exists and is of the right size. // Called at startup. // void CLIENT_STATE::check_file_existence() { unsigned int i; char path[MAXPATHLEN]; for (i=0; i<file_infos.size(); i++) { FILE_INFO* fip = file_infos[i]; if (fip->status < 0 && fip->downloadable()) { // file had an error; reset it so that we download again get_pathname(fip, path, sizeof(path)); msg_printf(fip->project, MSG_INFO, "Resetting file %s: %s", path, boincerror(fip->status) ); fip->reset(); continue; } if (cc_config.dont_check_file_sizes) continue; if (fip->status == FILE_PRESENT) { get_pathname(fip, path, sizeof(path)); double size; int retval = file_size(path, size); if (retval) { delete_project_owned_file(path, true); fip->status = FILE_NOT_PRESENT; msg_printf(fip->project, MSG_INFO, "File %s not found", path); } else if (fip->nbytes && (size != fip->nbytes)) { if (gstate.global_prefs.dont_verify_images && is_image_file(path)) continue; delete_project_owned_file(path, true); fip->status = FILE_NOT_PRESENT; msg_printf(fip->project, MSG_INFO, "File %s has wrong size: expected %.0f, got %.0f", path, fip->nbytes, size ); } } } }
// scan FILE_INFOs and create PERS_FILE_XFERs as needed. // NOTE: this doesn't start the file transfers // scan PERS_FILE_XFERs and delete finished ones. // bool CLIENT_STATE::create_and_delete_pers_file_xfers() { unsigned int i; FILE_INFO* fip; PERS_FILE_XFER *pfx; bool action = false; int retval; static double last_time; if (!clock_change && now - last_time < PERS_FILE_XFER_START_PERIOD) return false; last_time = now; // Look for FILE_INFOs for which we should start a transfer, // and make PERS_FILE_XFERs for them // for (i=0; i<file_infos.size(); i++) { fip = file_infos[i]; pfx = fip->pers_file_xfer; if (pfx) continue; if (fip->downloadable() && fip->status == FILE_NOT_PRESENT) { pfx = new PERS_FILE_XFER; pfx->init(fip, false); fip->pers_file_xfer = pfx; pers_file_xfers->insert(fip->pers_file_xfer); action = true; } else if (fip->uploadable() && fip->status == FILE_PRESENT && !fip->uploaded) { pfx = new PERS_FILE_XFER; pfx->init(fip, true); fip->pers_file_xfer = pfx; pers_file_xfers->insert(fip->pers_file_xfer); action = true; } } // Scan existing PERS_FILE_XFERs, looking for those that are done, // and deleting them // vector<PERS_FILE_XFER*>::iterator iter; iter = pers_file_xfers->pers_file_xfers.begin(); while (iter != pers_file_xfers->pers_file_xfers.end()) { pfx = *iter; // If the transfer finished, remove the PERS_FILE_XFER object // from the set and delete it // if (pfx->pers_xfer_done) { fip = pfx->fip; if (pfx->is_upload) { // file has been uploaded - delete if not sticky // if (!fip->sticky) { fip->delete_file(); } fip->uploaded = true; active_tasks.upload_notify_app(fip); } else if (fip->status >= 0) { // file transfer did not fail (non-negative status) // If this was a compressed download, rename .gzt to .gz // if (fip->download_gzipped) { char path[MAXPATHLEN], from_path[MAXPATHLEN], to_path[MAXPATHLEN]; get_pathname(fip, path, sizeof(path)); snprintf(from_path, sizeof(from_path), "%s.gzt", path); snprintf(to_path, sizeof(to_path), "%s.gz", path); boinc_rename(from_path, to_path); } // verify the file with RSA or MD5, and change permissions // retval = fip->verify_file(true, true, true); if (retval == ERR_IN_PROGRESS) { // do nothing } else if (retval) { msg_printf(fip->project, MSG_INTERNAL_ERROR, "Checksum or signature error for %s", fip->name ); fip->status = retval; } else { // Set the appropriate permissions depending on whether // it's an executable or normal file // retval = fip->set_permissions(); fip->status = FILE_PRESENT; } // if it's a user file, tell running apps to reread prefs // if (fip->is_user_file) { active_tasks.request_reread_prefs(fip->project); } // if it's a project file, make a link in project dir // if (fip->is_project_file) { PROJECT* p = fip->project; p->write_symlink_for_project_file(fip); p->update_project_files_downloaded_time(); } } iter = pers_file_xfers->pers_file_xfers.erase(iter); delete pfx; action = true; // `delete pfx' should have set pfx->fip->pfx to NULL assert (fip == NULL || fip->pers_file_xfer == NULL); } else { ++iter; } } return action; }