//! //! Function description. //! //! @param[in] file //! @param[in] file_updated //! //! @return //! //! @see //! //! @pre List of pre-conditions //! //! @post List of post conditions //! //! @note //! int atomic_file_get(atomic_file * file, boolean * file_updated) { int port = 0; int fd = 0; int ret = 0; int rc = 0; char *hash = NULL; char type[32] = ""; char hostname[512] = ""; char path[EUCA_MAX_PATH] = ""; char tmpsource[EUCA_MAX_PATH] = ""; char tmppath[EUCA_MAX_PATH] = ""; if (!file || !file_updated) { return (1); } ret = 0; *file_updated = FALSE; snprintf(file->tmpfile, EUCA_MAX_PATH, "%s", file->tmpfilebase); fd = safe_mkstemp(file->tmpfile); if (fd < 0) { LOGERROR("cannot open tmpfile '%s': check permissions\n", file->tmpfile); return (1); } if (chmod(file->tmpfile, 0600)) { LOGWARN("chmod failed: was able to create tmpfile '%s', but could not change file permissions\n", file->tmpfile); } close(fd); snprintf(tmpsource, EUCA_MAX_PATH, "%s", file->source); type[0] = tmppath[0] = path[0] = hostname[0] = '\0'; port = 0; tokenize_uri(tmpsource, type, hostname, &port, tmppath); snprintf(path, EUCA_MAX_PATH, "/%s", tmppath); if (!strcmp(type, "http")) { rc = http_get_timeout(file->source, file->tmpfile, 0, 0, 10, 15, NULL); if (rc) { LOGERROR("http client failed to fetch file URL=%s: check http server status\n", file->source); ret = 1; } } else if (!strcmp(type, "file")) { if (!strlen(path) || copy_file(path, file->tmpfile)) { LOGERROR("could not copy source file (%s) to dest file (%s): check permissions\n", path, file->tmpfile); ret = 1; } } else { LOGWARN("BUG: incompatible URI type (%s) passed to routine (only supports http, file)\n", type); ret = 1; } if (!ret) { if (file->dosort) { rc = atomic_file_sort_tmpfile(file); if (rc) { LOGWARN("could not sort tmpfile (%s) inplace: continuing without sort\n", file->tmpfile); } } // do checksum - only copy if file has changed hash = file2md5str(file->tmpfile); if (!hash) { LOGERROR("could not compute hash of tmpfile (%s): check permissions\n", file->tmpfile); ret = 1; } else { if (file->currhash) EUCA_FREE(file->currhash); file->currhash = hash; if (check_file(file->dest) || strcmp(file->currhash, file->lasthash)) { // hashes are different, put new file in place LOGDEBUG("update triggered due to file update (%s)\n", file->dest); LOGDEBUG("source and destination file contents have become different, triggering update of dest (%s)\n", file->dest); LOGDEBUG("renaming file %s -> %s\n", file->tmpfile, file->dest); if (rename(file->tmpfile, file->dest)) { LOGERROR("could not rename (move) source file '%s' to dest file '%s': check permissions\n", file->tmpfile, file->dest); ret = 1; } else { EUCA_FREE(file->lasthash); file->lasthash = strdup(file->currhash); *file_updated = TRUE; } } } } unlink(file->tmpfile); return (ret); }
//! //! //! //! @param[in] pMeta a pointer to the node controller (NC) metadata structure //! @param[in] serviceIds //! @param[in] serviceIdsLen //! //! @return //! //! @pre //! //! @note //! int doEnableService(ncMetadata * pMeta, serviceInfoType * serviceIds, int serviceIdsLen) { int i = 0; int rc = 0; int ret = 0; int done = 0; rc = initialize(pMeta, FALSE); if (rc) { return (1); } LOGDEBUG("invoked: userId=%s\n", SP(pMeta ? pMeta->userId : "UNKNOWN")); int enable_cc = 0; for (int i = 0; i < serviceIdsLen; i++) { if (strcmp(serviceIds[i].type, "cluster") == 0) { enable_cc = 1; } else if (strcmp(serviceIds[i].type, "node") == 0) { ret = doModifyNode(pMeta, serviceIds[i].name, "enabled"); } } if (serviceIdsLen < 1) { enable_cc = 1; } if (enable_cc != 1) goto done; sem_mywait(CONFIG); { if (config->ccState == SHUTDOWNCC) { LOGWARN("attempt to enable a shutdown CC, skipping.\n"); ret++; } else if (ccCheckState(0)) { LOGWARN("ccCheckState() returned failures, skipping.\n"); ret++; } else if (config->ccState != ENABLED) { LOGINFO("enabling service\n"); ret = 0; // tell monitor thread to (re)enable config->kick_monitor_running = 0; config->kick_network = 1; config->kick_dhcp = 1; config->kick_enabled = 1; ccChangeState(ENABLED); } } sem_mypost(CONFIG); if (config->ccState == ENABLED) { // wait for a minute to make sure CC is running again done = 0; for (i = 0; i < 60 && !done; i++) { sem_mywait(CONFIG); { if (config->kick_monitor_running) { done++; } } sem_mypost(CONFIG); if (!done) { LOGDEBUG("waiting for monitor to re-initialize (%d/60)\n", i); sleep(1); } } } done: LOGTRACE("done\n"); return (ret); }
//! //! Creates and initialize an NC stub entry //! //! @param[in] endpoint_uri the endpoint URI string //! @param[in] logfile the log file name string //! @param[in] homedir the home directory path string //! //! @return a pointer to the newly created NC stub structure //! scStub *scStubCreate(char *endpoint_uri, char *logfile, char *homedir) { char *uri = NULL; char *p = NULL; char *node_name = NULL; scStub *pStub = NULL; axutil_env_t *env = NULL; axis2_char_t *client_home; axis2_stub_t *stub; if (logfile) { env = axutil_env_create_all(logfile, AXIS2_LOG_LEVEL_TRACE); } else { env = axutil_env_create_all(NULL, 0); } if (homedir) { client_home = (axis2_char_t *) homedir; } else { client_home = AXIS2_GETENV("AXIS2C_HOME"); } if (client_home == NULL) { LOGERROR("cannot get AXIS2C_HOME"); return NULL; } if (endpoint_uri == NULL) { LOGERROR("empty endpoint_url"); return NULL; } uri = endpoint_uri; // extract node name from the endpoint p = strstr(uri, "://"); // find "http[s]://..." if (p == NULL) { LOGERROR("received invalid URI %s\n", uri); return NULL; } node_name = strdup(p + 3); // copy without the protocol prefix if (node_name == NULL) { LOGERROR("is out of memory\n"); return NULL; } if ((p = strchr(node_name, ':')) != NULL) *p = '\0'; // cut off the port if ((p = strchr(node_name, '/')) != NULL) *p = '\0'; // if there is no port //! @todo what if endpoint_uri, home, or env are NULL? stub = axis2_stub_create_EucalyptusSC(env, client_home, (axis2_char_t *) uri); if (stub) { if ((pStub = EUCA_ZALLOC(1, sizeof(scStub))) != NULL) { pStub->env = env; pStub->client_home = strdup((char *)client_home); pStub->endpoint_uri = (axis2_char_t *) strdup(endpoint_uri); pStub->node_name = (axis2_char_t *) strdup(node_name); pStub->stub = stub; if (pStub->client_home == NULL || pStub->endpoint_uri == NULL || pStub->node_name == NULL) { LOGWARN("out of memory (%s:%s:%d client_home=%s endpoint_uri=%s node_name=%s)", __FILE__, __FUNCTION__, __LINE__, pStub->client_home, pStub->endpoint_uri, pStub->node_name); } } else { LOGWARN("out of memory for 'st' (%s:%s:%d)\n", __FILE__, __FUNCTION__, __LINE__); } } else { LOGERROR("failed to create a stub for EucalyptusNC service (stub=%p env=%p client_home=%s)\n", stub, env, client_home); } EUCA_FREE(node_name); return (pStub); }
int connection_t::on_send_data() { if (m_enable_hb) { m_service_ptr->async_update_hb_element(m_conn_id); } bool all_finish = true; int transferred_size = 0; while (m_send_buffer.size()) { uint32_t msg_size = m_send_buffer.size(); int ret = ::send(m_socket, m_send_buffer.data(), msg_size, 0); if (0 == ret) { LOGWARN((CONNECTION_MODULE, "connection_t::on_send_data send ret == 0 socket fd:[%u]", m_socket)); async_close(m_conn_id, true, EV_PASSIVE_CLOSED); return 0; } else if (ret < 0) { LOGWARN((CONNECTION_MODULE, "connection_t::on_send_data send ret:[%d] socket fd:[%u] errno:[%m]", ret, m_socket, errno)); //! yunjie: 如果不是EAGAIN或EINTR, 那么就调用callback返回错误信息 if (errno != EAGAIN && errno != EINTR) { if (NULL != m_conn_event_callback) { m_conn_event_callback(EV_ERROR_OCCURRED, m_conn_status, m_conn_id); } } else { m_service_ptr->register_io_event( m_socket, WRITE_EVENT_FLAG, &connection_t::on_peer_event, (void*)this, false ); } return 0; } else { transferred_size += ret; m_send_buffer.drain_size(ret); if (ret != (int)msg_size) { m_service_ptr->register_io_event( m_socket, WRITE_EVENT_FLAG, &connection_t::on_peer_event, (void*)this, false ); all_finish = false; break; } } } //! yunjie: 使用者可以实现的虚方法 on_write_complete(transferred_size); if (all_finish) { m_sending_flag = false; } return 0; }
void cRoot::Start(void) { #ifdef _WIN32 HWND hwnd = GetConsoleWindow(); HMENU hmenu = GetSystemMenu(hwnd, FALSE); EnableMenuItem(hmenu, SC_CLOSE, MF_GRAYED); // Disable close button when starting up; it causes problems with our CTRL-CLOSE handling #endif cLogger::cListener * consoleLogListener = MakeConsoleListener(); cLogger::cListener * fileLogListener = new cFileListener(); cLogger::GetInstance().AttachListener(consoleLogListener); cLogger::GetInstance().AttachListener(fileLogListener); LOG("--- Started Log ---\n"); cDeadlockDetect dd; m_bStop = false; while (!m_bStop) { cTimer Time; long long mseconds = Time.GetNowTime(); m_bRestart = false; LoadGlobalSettings(); LOG("Creating new server instance..."); m_Server = new cServer(); LOG("Reading server config..."); cIniFile IniFile; if (!IniFile.ReadFile("settings.ini")) { LOGWARN("Regenerating settings.ini, all settings will be reset"); IniFile.AddHeaderComment(" This is the main server configuration"); IniFile.AddHeaderComment(" Most of the settings here can be configured using the webadmin interface, if enabled in webadmin.ini"); IniFile.AddHeaderComment(" See: http://wiki.mc-server.org/doku.php?id=configure:settings.ini for further configuration help"); } m_PrimaryServerVersion = IniFile.GetValueI("Server", "PrimaryServerVersion", 0); if (m_PrimaryServerVersion == 0) { m_PrimaryServerVersion = cProtocolRecognizer::PROTO_VERSION_LATEST; } else { // Make a note in the log that the primary server version is explicitly set in the ini file LOGINFO("Primary server version set explicitly to %d.", m_PrimaryServerVersion); } LOG("Starting server..."); m_MojangAPI.Start(IniFile); // Mojang API needs to be started before plugins, so that plugins may use it for DB upgrades on server init if (!m_Server->InitServer(IniFile)) { LOGERROR("Failure starting server, aborting..."); return; } m_WebAdmin = new cWebAdmin(); m_WebAdmin->Init(); LOGD("Loading settings..."); m_GroupManager = new cGroupManager(); m_CraftingRecipes = new cCraftingRecipes; m_FurnaceRecipe = new cFurnaceRecipe(); LOGD("Loading worlds..."); LoadWorlds(IniFile); LOGD("Loading plugin manager..."); m_PluginManager = new cPluginManager(); m_PluginManager->ReloadPluginsNow(IniFile); LOGD("Loading MonsterConfig..."); m_MonsterConfig = new cMonsterConfig; // This sets stuff in motion LOGD("Starting Authenticator..."); m_Authenticator.Start(IniFile); LOGD("Starting worlds..."); StartWorlds(); if (IniFile.GetValueSetB("DeadlockDetect", "Enabled", true)) { LOGD("Starting deadlock detector..."); dd.Start(IniFile.GetValueSetI("DeadlockDetect", "IntervalSec", 20)); } IniFile.WriteFile("settings.ini"); LOGD("Finalising startup..."); m_Server->Start(); m_WebAdmin->Start(); #if !defined(ANDROID_NDK) LOGD("Starting InputThread..."); m_InputThread = new cThread( InputThread, this, "cRoot::InputThread"); m_InputThread->Start( false); // We should NOT wait? Otherwise we can't stop the server from other threads than the input thread #endif long long finishmseconds = Time.GetNowTime(); finishmseconds -= mseconds; LOG("Startup complete, took %lld ms!", finishmseconds); #ifdef _WIN32 EnableMenuItem(hmenu, SC_CLOSE, MF_ENABLED); // Re-enable close button #endif while (!m_bStop && !m_bRestart && !m_TerminateEventRaised) // These are modified by external threads { cSleep::MilliSleep(1000); } if (m_TerminateEventRaised) { m_bStop = true; } #if !defined(ANDROID_NDK) delete m_InputThread; m_InputThread = NULL; #endif // Stop the server: m_WebAdmin->Stop(); LOG("Shutting down server..."); m_Server->Shutdown(); LOGD("Shutting down deadlock detector..."); dd.Stop(); LOGD("Stopping world threads..."); StopWorlds(); LOGD("Stopping authenticator..."); m_Authenticator.Stop(); LOGD("Freeing MonsterConfig..."); delete m_MonsterConfig; m_MonsterConfig = NULL; delete m_WebAdmin; m_WebAdmin = NULL; LOGD("Unloading recipes..."); delete m_FurnaceRecipe; m_FurnaceRecipe = NULL; delete m_CraftingRecipes; m_CraftingRecipes = NULL; LOGD("Forgetting groups..."); delete m_GroupManager; m_GroupManager = NULL; LOGD("Unloading worlds..."); UnloadWorlds(); LOGD("Stopping plugin manager..."); delete m_PluginManager; m_PluginManager = NULL; cItemHandler::Deinit(); LOG("Cleaning up..."); delete m_Server; m_Server = NULL; LOG("Shutdown successful!"); } LOG("--- Stopped Log ---"); cLogger::GetInstance().DetachListener(consoleLogListener); delete consoleLogListener; cLogger::GetInstance().DetachListener(fileLogListener); delete fileLogListener; }
cTerrainCompositionGenPtr cTerrainCompositionGen::CreateCompositionGen(cIniFile & a_IniFile, cBiomeGenPtr a_BiomeGen, cTerrainShapeGenPtr a_ShapeGen, int a_Seed) { AString CompoGenName = a_IniFile.GetValueSet("Generator", "CompositionGen", ""); if (CompoGenName.empty()) { LOGWARN("[Generator] CompositionGen value not set in world.ini, using \"Biomal\"."); CompoGenName = "Biomal"; } // Compositor list is alpha-sorted cTerrainCompositionGenPtr res; if (NoCaseCompare(CompoGenName, "Biomal") == 0) { res = CreateCompoGenBiomal(a_Seed); } else if (NoCaseCompare(CompoGenName, "BiomalNoise3D") == 0) { // The composition that used to be provided with BiomalNoise3D is now provided by the Biomal compositor: res = CreateCompoGenBiomal(a_Seed); } else if (NoCaseCompare(CompoGenName, "Classic") == 0) { res = std::make_shared<cCompoGenClassic>(); } else if (NoCaseCompare(CompoGenName, "DebugBiomes") == 0) { res = std::make_shared<cCompoGenDebugBiomes>(); } else if (NoCaseCompare(CompoGenName, "DistortedHeightmap") == 0) { // The composition that used to be provided with DistortedHeightmap is now provided by the Biomal compositor: res = CreateCompoGenBiomal(a_Seed); } else if (NoCaseCompare(CompoGenName, "End") == 0) { res = std::make_shared<cEndGen>(a_Seed); } else if (NoCaseCompare(CompoGenName, "Nether") == 0) { res = std::make_shared<cCompoGenNether>(a_Seed); } else if (NoCaseCompare(CompoGenName, "Noise3D") == 0) { // The composition that used to be provided with Noise3D is now provided by the Biomal compositor: res = CreateCompoGenBiomal(a_Seed); } else if (NoCaseCompare(CompoGenName, "SameBlock") == 0) { res = std::make_shared<cCompoGenSameBlock>(); } else { LOGWARN("Unknown CompositionGen \"%s\", using \"Biomal\" instead.", CompoGenName.c_str()); a_IniFile.SetValue("Generator", "CompositionGen", "Biomal"); return CreateCompositionGen(a_IniFile, a_BiomeGen, a_ShapeGen, a_Seed); } ASSERT(res != nullptr); // Read the settings from the ini file: res->InitializeCompoGen(a_IniFile); return cTerrainCompositionGenPtr(res); }
//! //! Creates and initialize an NC stub entry //! //! @param[in] endpoint_uri the endpoint URI string //! @param[in] logfile the log file name string //! @param[in] homedir the home directory path string //! //! @return a pointer to the newly created NC stub structure //! ncStub *ncStubCreate(char *endpoint_uri, char *logfile, char *homedir) { char *uri = NULL; char *p = NULL; char *node_name = NULL; axutil_env_t *env = NULL; axis2_char_t *client_home = NULL; axis2_stub_t *stub = NULL; ncStub *st = NULL; if (logfile) { env = axutil_env_create_all(logfile, AXIS2_LOG_LEVEL_TRACE); } else { env = axutil_env_create_all(NULL, 0); } if (homedir) { client_home = (axis2_char_t *) homedir; } else { client_home = AXIS2_GETENV("AXIS2C_HOME"); } if (client_home == NULL) { LOGERROR("fakeNC: ERROR: cannot get AXIS2C_HOME"); return NULL; } if (endpoint_uri == NULL) { LOGERROR("fakeNC: ERROR: empty endpoint_url"); return NULL; } uri = endpoint_uri; // extract node name from the endpoint p = strstr(uri, "://"); // find "http[s]://..." if (p == NULL) { LOGERROR("fakeNC: ncStubCreate received invalid URI %s\n", uri); return NULL; } node_name = strdup(p + 3); // copy without the protocol prefix if (node_name == NULL) { LOGERROR("fakeNC: ncStubCreate is out of memory\n"); return NULL; } if ((p = strchr(node_name, ':')) != NULL) *p = '\0'; // cut off the port if ((p = strchr(node_name, '/')) != NULL) *p = '\0'; // if there is no port LOGDEBUG("fakeNC: DEBUG: requested URI %s\n", uri); // see if we should redirect to a local broker if (strstr(uri, "EucalyptusBroker")) { uri = "http://localhost:8773/services/EucalyptusBroker"; LOGDEBUG("fakeNC: DEBUG: redirecting request to %s\n", uri); } //! @todo what if endpoint_uri, home, or env are NULL? stub = axis2_stub_create_EucalyptusNC(env, client_home, (axis2_char_t *) uri); if (stub && (st = EUCA_ZALLOC(1, sizeof(ncStub)))) { st->env = env; st->client_home = strdup((char *)client_home); st->endpoint_uri = (axis2_char_t *) strdup(endpoint_uri); st->node_name = (axis2_char_t *) strdup(node_name); st->stub = stub; if (st->client_home == NULL || st->endpoint_uri == NULL) { LOGWARN("fakeNC: WARNING: out of memory"); } } else { LOGWARN("fakeNC: WARNING: out of memory"); } EUCA_FREE(node_name); return (st); }
//! //! //! //! @param[in] inst a pointer to the instance structure //! @param[in] in a transparent pointer (unused) //! //! @return //! //! @pre The inst pointer must not be NULL. //! //! @note //! int instIpSync(ccInstance * inst, void *in) { int ret = 0; if (!inst) { return (1); } else if ((strcmp(inst->state, "Pending") && strcmp(inst->state, "Extant"))) { return (0); } LOGDEBUG("instanceId=%s CCpublicIp=%s CCprivateIp=%s CCprivateMac=%s CCvlan=%d CCnetworkIndex=%d NCpublicIp=%s NCprivateIp=%s NCprivateMac=%s " "NCvlan=%d NCnetworkIndex=%d\n", inst->instanceId, inst->ccnet.publicIp, inst->ccnet.privateIp, inst->ccnet.privateMac, inst->ccnet.vlan, inst->ccnet.networkIndex, inst->ncnet.publicIp, inst->ncnet.privateIp, inst->ncnet.privateMac, inst->ncnet.vlan, inst->ncnet.networkIndex); if (inst->ccnet.vlan == 0 && inst->ccnet.networkIndex == 0 && inst->ccnet.publicIp[0] == '\0' && inst->ccnet.privateIp[0] == '\0' && inst->ccnet.privateMac[0] == '\0') { // ccnet is completely empty, make a copy of ncnet LOGDEBUG("ccnet is empty, copying ncnet\n"); memcpy(&(inst->ccnet), &(inst->ncnet), sizeof(netConfig)); return (1); } // IP cases // 1.) local CC cache has no IP info for VM, NC VM has no IP info // - do nothing // 2.) local CC cache has no IP info, NC VM has IP info // - ingress NC info, kick_network // 3.) local CC cache has IP info, NC VM has no IP info // - send ncAssignAddress // 4.) local CC cache has IP info, NC VM has different IP info // - ingress NC info, kick_network // 5.) local CC cache has IP info, NC VM has same IP info // - do nothing if ((inst->ccnet.publicIp[0] == '\0' || !strcmp(inst->ccnet.publicIp, "0.0.0.0")) && (inst->ncnet.publicIp[0] != '\0' && strcmp(inst->ncnet.publicIp, "0.0.0.0"))) { // case 2 LOGDEBUG("CC publicIp is empty, NC publicIp is set\n"); snprintf(inst->ccnet.publicIp, 24, "%s", inst->ncnet.publicIp); ret++; } else if (((inst->ccnet.publicIp[0] != '\0' && strcmp(inst->ccnet.publicIp, "0.0.0.0")) && (inst->ncnet.publicIp[0] != '\0' && strcmp(inst->ncnet.publicIp, "0.0.0.0"))) && strcmp(inst->ccnet.publicIp, inst->ncnet.publicIp)) { // case 4 LOGDEBUG("CC publicIp and NC publicIp differ\n"); snprintf(inst->ccnet.publicIp, 24, "%s", inst->ncnet.publicIp); ret++; } // VLAN cases if (inst->ccnet.vlan != inst->ncnet.vlan) { // problem LOGERROR("CC and NC vlans differ instanceId=%s CCvlan=%d NCvlan=%d\n", inst->instanceId, inst->ccnet.vlan, inst->ncnet.vlan); } inst->ccnet.vlan = inst->ncnet.vlan; if (inst->ccnet.vlan >= 0) { if (!vnetconfig->networks[inst->ccnet.vlan].active) { LOGWARN("detected instance from NC that is running in a currently inactive network; will attempt to re-activate network '%d'\n", inst->ccnet.vlan); ret++; } } // networkIndex cases if (inst->ccnet.networkIndex != inst->ncnet.networkIndex) { // problem LOGERROR("CC and NC networkIndicies differ instanceId=%s CCnetworkIndex=%d NCnetworkIndex=%d\n", inst->instanceId, inst->ccnet.networkIndex, inst->ncnet.networkIndex); } inst->ccnet.networkIndex = inst->ncnet.networkIndex; // mac addr cases if (strcmp(inst->ccnet.privateMac, inst->ncnet.privateMac)) { // problem; LOGERROR("CC and NC mac addrs differ instanceId=%s CCmac=%s NCmac=%s\n", inst->instanceId, inst->ccnet.privateMac, inst->ncnet.privateMac); } snprintf(inst->ccnet.privateMac, 24, "%s", inst->ncnet.privateMac); // privateIp cases if (strcmp(inst->ccnet.privateIp, inst->ncnet.privateIp)) { // sync em snprintf(inst->ccnet.privateIp, 24, "%s", inst->ncnet.privateIp); } return (ret); }
/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // cTerrainCompositionGen: cTerrainCompositionGen * cTerrainCompositionGen::CreateCompositionGen(cIniFile & a_IniFile, cBiomeGen & a_BiomeGen, cTerrainHeightGen & a_HeightGen, int a_Seed) { AString CompoGenName = a_IniFile.GetValueSet("Generator", "CompositionGen", ""); if (CompoGenName.empty()) { LOGWARN("[Generator] CompositionGen value not set in world.ini, using \"Biomal\"."); CompoGenName = "Biomal"; a_IniFile.SetValue("Generator", "CompositionGen", CompoGenName); } cTerrainCompositionGen * res = NULL; if (NoCaseCompare(CompoGenName, "sameblock") == 0) { res = new cCompoGenSameBlock; } else if (NoCaseCompare(CompoGenName, "debugbiomes") == 0) { res = new cCompoGenDebugBiomes; } else if (NoCaseCompare(CompoGenName, "classic") == 0) { res = new cCompoGenClassic; } else if (NoCaseCompare(CompoGenName, "DistortedHeightmap") == 0) { res = new cDistortedHeightmap(a_Seed, a_BiomeGen); } else if (NoCaseCompare(CompoGenName, "end") == 0) { res = new cEndGen(a_Seed); } else if (NoCaseCompare(CompoGenName, "nether") == 0) { res = new cCompoGenNether(a_Seed); } else if (NoCaseCompare(CompoGenName, "Noise3D") == 0) { res = new cNoise3DComposable(a_Seed); } else if (NoCaseCompare(CompoGenName, "biomal") == 0) { res = new cCompoGenBiomal(a_Seed); /* // Performance-testing: LOGINFO("Measuring performance of cCompoGenBiomal..."); clock_t BeginTick = clock(); for (int x = 0; x < 500; x++) { cChunkDesc Desc(200 + x * 8, 200 + x * 8); a_BiomeGen->GenBiomes(Desc.GetChunkX(), Desc.GetChunkZ(), Desc.GetBiomeMap()); a_HeightGen->GenHeightMap(Desc.GetChunkX(), Desc.GetChunkZ(), Desc.GetHeightMap()); res->ComposeTerrain(Desc); } clock_t Duration = clock() - BeginTick; LOGINFO("CompositionGen for 500 chunks took %d ticks (%.02f sec)", Duration, (double)Duration / CLOCKS_PER_SEC); //*/ } else { LOGWARN("Unknown CompositionGen \"%s\", using \"Biomal\" instead.", CompoGenName.c_str()); a_IniFile.DeleteValue("Generator", "CompositionGen"); a_IniFile.SetValue("Generator", "CompositionGen", "Biomal"); return CreateCompositionGen(a_IniFile, a_BiomeGen, a_HeightGen, a_Seed); } ASSERT(res != NULL); // Read the settings from the ini file: res->InitializeCompoGen(a_IniFile); return res; }
void cRoot::Start(void) { cDeadlockDetect dd; delete m_Log; m_Log = new cMCLogger(); m_bStop = false; while (!m_bStop) { cTimer Time; long long mseconds = Time.GetNowTime(); m_bRestart = false; LoadGlobalSettings(); LOG("Creating new server instance..."); m_Server = new cServer(); LOG("Reading server config..."); cIniFile IniFile; if (!IniFile.ReadFile("settings.ini")) { LOGWARN("Regenerating settings.ini, all settings will be reset"); IniFile.AddHeaderComment(" This is the main server configuration"); IniFile.AddHeaderComment(" Most of the settings here can be configured using the webadmin interface, if enabled in webadmin.ini"); IniFile.AddHeaderComment(" See: http://www.mc-server.org/wiki/doku.php?id=configure:settings.ini for further configuration help"); } m_PrimaryServerVersion = IniFile.GetValueI("Server", "PrimaryServerVersion", 0); if (m_PrimaryServerVersion == 0) { m_PrimaryServerVersion = cProtocolRecognizer::PROTO_VERSION_LATEST; } else { // Make a note in the log that the primary server version is explicitly set in the ini file LOGINFO("Primary server version set explicitly to %d.", m_PrimaryServerVersion); } LOG("Starting server..."); if (!m_Server->InitServer(IniFile)) { LOGERROR("Failure starting server, aborting..."); return; } m_WebAdmin = new cWebAdmin(); m_WebAdmin->Init(); LOGD("Loading settings..."); m_GroupManager = new cGroupManager(); m_CraftingRecipes = new cCraftingRecipes; m_FurnaceRecipe = new cFurnaceRecipe(); LOGD("Loading worlds..."); LoadWorlds(IniFile); LOGD("Loading plugin manager..."); m_PluginManager = new cPluginManager(); m_PluginManager->ReloadPluginsNow(IniFile); LOGD("Loading MonsterConfig..."); m_MonsterConfig = new cMonsterConfig; // This sets stuff in motion LOGD("Starting Authenticator..."); m_Authenticator.Start(IniFile); IniFile.WriteFile("settings.ini"); LOGD("Starting worlds..."); StartWorlds(); LOGD("Starting deadlock detector..."); dd.Start(); LOGD("Finalising startup..."); m_Server->Start(); m_WebAdmin->Start(); #if !defined(ANDROID_NDK) LOGD("Starting InputThread..."); m_InputThread = new cThread( InputThread, this, "cRoot::InputThread" ); m_InputThread->Start( false ); // We should NOT wait? Otherwise we can´t stop the server from other threads than the input thread #endif long long finishmseconds = Time.GetNowTime(); finishmseconds -= mseconds; LOG("Startup complete, took %i ms!", finishmseconds); while (!m_bStop && !m_bRestart) // These are modified by external threads { cSleep::MilliSleep(1000); } #if !defined(ANDROID_NDK) delete m_InputThread; m_InputThread = NULL; #endif // Deallocate stuffs LOG("Shutting down server..."); m_Server->Shutdown(); LOGD("Shutting down deadlock detector..."); dd.Stop(); LOGD("Stopping world threads..."); StopWorlds(); LOGD("Stopping authenticator..."); m_Authenticator.Stop(); LOGD("Freeing MonsterConfig..."); delete m_MonsterConfig; m_MonsterConfig = NULL; delete m_WebAdmin; m_WebAdmin = NULL; LOGD("Unloading recipes..."); delete m_FurnaceRecipe; m_FurnaceRecipe = NULL; delete m_CraftingRecipes; m_CraftingRecipes = NULL; LOGD("Forgetting groups..."); delete m_GroupManager; m_GroupManager = 0; LOGD("Unloading worlds..."); UnloadWorlds(); LOGD("Stopping plugin manager..."); delete m_PluginManager; m_PluginManager = NULL; cItemHandler::Deinit(); cBlockHandler::Deinit(); LOG("Cleaning up..."); //delete HeartBeat; HeartBeat = 0; delete m_Server; m_Server = 0; LOG("Shutdown successful!"); } delete m_Log; m_Log = 0; }
void task_service_t::exec_task(thread_t* thd_) { deque<async_method_t> tasks; uint32_t all_task_num = 0; uint32_t thread_num = m_thread_group.size(); if (NULL == thd_) { LOGWARN((TASK_SERVICE_MODULE, "task_service_t::exec_task service(%s) thread is NULL, return", m_service_name.c_str())); return; } if (!thread_num) { LOGWARN((TASK_SERVICE_MODULE, "task_service_t::exec_task service(%s) thread_num equals zero, return", m_service_name.c_str())); return; } while (!m_stop_signal || !m_task_queue.empty()) { struct timeval cached_now; //! yunjie: prepare the task buffer tasks.clear(); while (1) { //! yunjie: 处理定时事件 m_timer_manager.flush_time(); cached_now = m_timer_manager.get_cached_time(); //! yunjie: 如果有timer时间超时, 将会在函数内部执行callback m_timer_manager.exec(); //! yunjie; 进行网络IO检测, 并会调用相应 读/写 回调 int wake_num = m_io_handler.wait_io_notification(); //! yunjie: 本来是采用动态调整m_fetch_num_per_loop来平衡每个线程的任务抓取量, 发现并没有太大意义, 改为一次性全部获取所有任务 m_task_queue.fetch_task(tasks, all_task_num, m_fetch_num_per_loop); if (wake_num || tasks.size() || m_stop_signal) //! yunjie: 需要判断m_stop_signal, 否则外部投递stop信号号会发生join永远阻塞 { break; } #if USE_COND_VAR thd_->cond_wait(cached_now, 0, TIMEDOUT_US); #else thread_t::usleep(TIMEDOUT_US); #endif } //! yunjie: calc the fetch_num_per_loop if (thread_num != 1) { m_fetch_num_per_loop = all_task_num / thread_num; if (!m_fetch_num_per_loop) { m_fetch_num_per_loop = MIN_TASK_FETCH_NUM; } if (m_fetch_num_per_loop > MAX_TASK_FETCH_NUM) { m_fetch_num_per_loop = MAX_TASK_FETCH_NUM; } } //! yunjie: 处理异步请求 for (deque<async_method_t>::iterator it = tasks.begin(); it != tasks.end(); ++it) { (*it)(); it->release(); } } m_timer_manager.clear(); assert(0 == m_task_queue.size()); }
int cLuaState::CallFunctionWithForeignParams( const AString & a_FunctionName, cLuaState & a_SrcLuaState, int a_SrcParamStart, int a_SrcParamEnd ) { ASSERT(IsValid()); ASSERT(a_SrcLuaState.IsValid()); // Store the stack position before any changes int OldTop = lua_gettop(m_LuaState); // Push the function to call, including the error handler: if (!PushFunction(a_FunctionName.c_str())) { LOGWARNING("Function '%s' not found", a_FunctionName.c_str()); lua_pop(m_LuaState, 2); return -1; } // Copy the function parameters to the target state if (CopyStackFrom(a_SrcLuaState, a_SrcParamStart, a_SrcParamEnd) < 0) { // Something went wrong, fix the stack and exit lua_pop(m_LuaState, 2); m_NumCurrentFunctionArgs = -1; m_CurrentFunctionName.clear(); return -1; } // Call the function, with an error handler: int s = lua_pcall(m_LuaState, a_SrcParamEnd - a_SrcParamStart + 1, LUA_MULTRET, OldTop + 1); if (ReportErrors(s)) { LOGWARN("Error while calling function '%s' in '%s'", a_FunctionName.c_str(), m_SubsystemName.c_str()); // Fix the stack. // We don't know how many values have been pushed, so just get rid of any that weren't there initially int CurTop = lua_gettop(m_LuaState); if (CurTop > OldTop) { lua_pop(m_LuaState, CurTop - OldTop); } // Reset the internal checking mechanisms: m_NumCurrentFunctionArgs = -1; m_CurrentFunctionName.clear(); // Make Lua think everything is okay and return 0 values, so that plugins continue executing. // The failure is indicated by the zero return values. return 0; } // Reset the internal checking mechanisms: m_NumCurrentFunctionArgs = -1; m_CurrentFunctionName.clear(); // Remove the error handler from the stack: lua_remove(m_LuaState, OldTop + 1); // Return the number of return values: return lua_gettop(m_LuaState) - OldTop; }
void serialport_set_baudrate(unsigned int baudrate) { switch(baudrate) { case 2400: cfsetispeed(&term,B2400); cfsetospeed(&term,B2400); break; case 4800: cfsetispeed(&term,B4800); cfsetospeed(&term,B4800); break; case 9600: cfsetispeed(&term,B9600); cfsetospeed(&term,B9600); break; case 19200: cfsetispeed(&term,B19200); cfsetospeed(&term,B19200); break; case 38400: cfsetispeed(&term,B38400); cfsetospeed(&term,B38400); break; case 57600: cfsetispeed(&term,B57600); cfsetospeed(&term,B57600); break; case 115200: cfsetispeed(&term,B115200); cfsetospeed(&term,B115200); break; case 230400: cfsetispeed(&term,B230400); cfsetospeed(&term,B230400); break; #ifndef __APPLE__ case 460800: cfsetispeed(&term,B460800); cfsetospeed(&term,B460800); break; case 921600: cfsetispeed(&term,B921600); cfsetospeed(&term,B921600); break; #endif default: LOGWARN("serialport_set_baudrate: baud rate %d may not work", baudrate); cfsetispeed(&term,baudrate); cfsetospeed(&term,baudrate); break; } }
/// Creates the underlying O/S file handle. /// /// @param[in] pszName name of the pipe /// @param[in] bServer true if this is a server end, false if it is a client /// @param[in] bExclusive false if this is a pipe that can be shared by multiple clients or servers /// @param[in] bReader true if this is the reading end of a pipe, false if it is the writing end /// @return the O/S file handle static CTimeoutIO::FILE_REFERENCE _CreatePipe (const TCHAR *pszName, bool bServer, bool bExclusive, bool bReader) { #ifdef _WIN32 HANDLE handle; if (bServer) { SECURITY_DESCRIPTOR sd; SECURITY_ATTRIBUTES sa; InitializeSecurityDescriptor (&sd, SECURITY_DESCRIPTOR_REVISION); // TODO [PLAT-1119] Get a SDDL from the registry for the DACL (and pass it into this library) SetSecurityDescriptorDacl (&sd, TRUE, NULL, FALSE); ZeroMemory (&sa, sizeof (sa)); sa.nLength = sizeof (sa); sa.lpSecurityDescriptor = &sd; sa.bInheritHandle = FALSE; handle = CreateNamedPipe ( pszName, (bReader ? PIPE_ACCESS_INBOUND : PIPE_ACCESS_OUTBOUND) | (bExclusive ? FILE_FLAG_FIRST_PIPE_INSTANCE : 0) | FILE_FLAG_OVERLAPPED, (bExclusive ? PIPE_TYPE_BYTE | PIPE_READMODE_BYTE : PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE) | PIPE_WAIT | PIPE_REJECT_REMOTE_CLIENTS, bExclusive ? 1 : PIPE_UNLIMITED_INSTANCES, 0, 0, 0, &sa); } else { // TODO: share or exclusive? We want a 1:1 on the pipe we've connected to - the server will open another for new clients handle = CreateFile (pszName, bReader ? GENERIC_READ : GENERIC_WRITE, 0/* bReader ? FILE_SHARE_READ : FILE_SHARE_WRITE */, NULL, OPEN_EXISTING, FILE_FLAG_OVERLAPPED, NULL); } if (handle == INVALID_HANDLE_VALUE) { DWORD dwError = GetLastError (); LOGWARN (TEXT ("Couldn't create pipe ") << pszName << TEXT(", error ") << dwError); SetLastError (dwError); return NULL; } LOGINFO (TEXT ("Created pipe ") << pszName); return handle; #else /* ifdef _WIN32 */ if (bExclusive) { if (mkfifo (pszName, 0666)) { int ec = GetLastError (); LOGWARN (TEXT ("Couldn't create pipe ") << pszName << TEXT (", error ") << ec); SetLastError (ec); return 0; } CThread *poOpener = new CNamedPipeOpenThread (pszName, bReader ? O_WRONLY : O_RDONLY); poOpener->Start (); CThread::Release (poOpener); int file = open (pszName, bReader ? O_RDONLY : O_WRONLY); if (file <= 0) { int ec = GetLastError (); LOGWARN (TEXT ("Couldn't open pipe ") << pszName << TEXT (", error ") << ec); if (unlink (pszName)) { LOGWARN (TEXT ("Couldn't delete pipe ") << pszName << TEXT (", error ") << GetLastError ()); } SetLastError (ec); return 0; } LOGINFO (TEXT ("Created pipe ") << pszName); return file; } else { int sock; sock = socket (AF_UNIX, SOCK_STREAM, 0); if (sock < 0) { int ec = GetLastError (); LOGWARN (TEXT ("Couldn't open pipe ") << pszName << TEXT (", error ") << ec); SetLastError (ec); return 0; } if (!_SetDefaultSocketOptions (sock)) { int ec = GetLastError (); close (sock); LOGWARN (TEXT ("Couldn't set default options ") << pszName << TEXT (", error ") << ec); SetLastError (ec); return 0; } struct sockaddr_un addr; addr.sun_family = AF_UNIX; StringCbPrintf (addr.sun_path, sizeof (addr.sun_path), TEXT ("%s"), pszName); if (bServer) { if (!unlink (pszName)) { LOGINFO (TEXT ("Deleted previous instance of ") << pszName); } if (bind (sock, (struct sockaddr*)&addr, sizeof (addr.sun_family) + _tcslen (addr.sun_path))) { int ec = GetLastError (); close (sock); LOGWARN (TEXT ("Couldn't open pipe ") << pszName << TEXT (", error ") << ec); SetLastError (ec); return 0; } if (fcntl (sock, F_SETFL, O_NONBLOCK) || listen (sock, 0)) { int ec = GetLastError (); close (sock); LOGWARN (TEXT ("Couldn't open pipe ") << pszName << TEXT (", error ") << ec); SetLastError (ec); return 0; } LOGINFO (TEXT ("Created server Unix Domain Socket ") << pszName); } else { if (connect (sock, (struct sockaddr*)&addr, sizeof (addr.sun_family) + _tcslen (addr.sun_path))) { int ec = GetLastError (); close (sock); LOGWARN (TEXT ("Couldn't open pipe ") << pszName << TEXT (", error ") << ec); switch (ec) { case EAGAIN : LOGDEBUG (TEXT ("Translating EAGAIN to ENOENT")); ec = ENOENT; break; case ECONNREFUSED : LOGDEBUG (TEXT ("Translating ECONNREFUSED to ENOENT")); ec = ENOENT; break; } SetLastError (ec); return 0; } LOGDEBUG (TEXT ("Connection accepted, waiting for handshake confirmation")); if ((recv (sock, addr.sun_path, 1, 0) != 1) || fcntl (sock, F_SETFL, O_NONBLOCK)) { int ec = GetLastError (); close (sock); LOGWARN (TEXT ("Handshake not received on ") << pszName << TEXT (", error ") << ec); switch (ec) { case EAGAIN : LOGDEBUG (TEXT ("Translating EAGAIN to ENOENT")); ec = ENOENT; break; } SetLastError (ec); return 0; } LOGINFO (TEXT ("Connected to Unix Domain Socket ") << pszName); } return sock; } #endif /* ifdef _WIN32 */ }
//! //! //! //! @param[in] path //! @param[in] offset //! @param[in] lodev name of the loop device //! @param[in] lodev_size //! //! @return EUCA_OK on success or the following error codes: //! \li EUCA_ERROR: if any error occured. //! \li EUCA_INVALID_ERROR: if any parameter does not meet the preconditions. //! //! @pre Both path and lodev parameters must not be NULL. //! //! @post On success, the loop device is attached. //! int diskutil_loop(const char *path, const long long offset, char *lodev, int lodev_size) { int i = 0; int ret = EUCA_OK; char *ptr = NULL; char *output = NULL; boolean done = FALSE; boolean found = FALSE; boolean do_log = FALSE; if (path && lodev) { // we retry because we cannot atomically obtain a free loopback device on all distros (some // versions of 'losetup' allow a file argument with '-f' options, but some do not) for (i = 0, done = FALSE, found = FALSE; i < LOOP_RETRIES; i++) { sem_p(loop_sem); { output = pruntf(TRUE, "%s %s -f", helpers_path[ROOTWRAP], helpers_path[LOSETUP]); } sem_v(loop_sem); if (output == NULL) { // there was a problem break; } if (strstr(output, "/dev/loop")) { strncpy(lodev, output, lodev_size); if ((ptr = strrchr(lodev, '\n')) != NULL) { *ptr = '\0'; found = TRUE; } } EUCA_FREE(output); if (found) { do_log = ((i + 1) == LOOP_RETRIES); // log error on last try only LOGDEBUG("attaching file %s\n", path); LOGDEBUG(" to %s at offset %lld\n", lodev, offset); sem_p(loop_sem); { char str_offset[64]; snprintf(str_offset, sizeof(str_offset), "%lld", offset); output = execlp_output(do_log, helpers_path[ROOTWRAP], helpers_path[LOSETUP], "-o", str_offset, lodev, path, NULL); } sem_v(loop_sem); if (output == NULL) { LOGDEBUG("cannot attach to loop device %s (will retry)\n", lodev); } else { EUCA_FREE(output); done = TRUE; break; } } sleep(1); found = FALSE; } if (!done) { LOGERROR("cannot find free loop device or attach to one\n"); ret = EUCA_ERROR; } return (ret); } LOGWARN("cannot attach to loop device. path=%s, lodev=%s\n", SP(path), SP(lodev)); return (EUCA_INVALID_ERROR); }
/// Accepts an incoming connection on a server pipe. /// /// @param[in] timeout maximum time to wait for a client in milliseconds /// @return this end of a pipe connected to the client, or NULL if none was available CNamedPipe *CNamedPipe::Accept (unsigned long timeout) { assert (IsServer ()); #ifdef _WIN32 if (!ConnectNamedPipe (GetFile (), GetOverlapped ())) { if (GetLastError () != ERROR_PIPE_CONNECTED) { if (!WaitOnOverlapped (timeout)) { DWORD dwError = GetLastError (); LOGWARN (TEXT ("Overlapped result not available, error ") << dwError); SetLastError (dwError); return NULL; } } } HANDLE handle = _CreatePipe (GetName (), IsServer (), false, IsReader ()); if (!handle) { DWORD dwError = GetLastError (); LOGWARN (TEXT ("Couldn't create replacement pipe for server, error ") << dwError); SetLastError (dwError); return NULL; } CNamedPipe *poClient = new CNamedPipe (GetFile (), GetName (), false, IsReader ()); SetFile (handle); return poClient; #else failedOperation: struct sockaddr_un addr; bool bLazyWait = false; if (IsLazyClosing ()) { bLazyWait = true; timeout = IsLazyClosing (); } timeoutOperation: int sock; if (BeginOverlapped (timeout, true)) { socklen_t len = sizeof (addr); sock = accept (GetFile (), (struct sockaddr*)&addr, &len); EndOverlapped (); } else { sock = -1; } if (sock < 0) { int ec = GetLastError (); if (ec == EINTR) { LOGDEBUG (TEXT ("Accept interrupted")); if (IsLazyClosing ()) { if (bLazyWait) { LOGINFO (TEXT ("Closing file on idle timeout")); Close (); } } if (!IsClosed () && !bLazyWait) { bLazyWait = true; timeout = IsLazyClosing (); LOGDEBUG (TEXT ("Resuming operation with idle timeout of ") << timeout << TEXT ("ms")); goto timeoutOperation; } } LOGWARN (TEXT ("Couldn't accept client, error ") << ec); SetLastError (ec); return NULL; } LOGINFO (TEXT ("Connection accepted on ") << GetName ()); if (!_SetDefaultSocketOptions (sock)) { int ec = GetLastError (); close (sock); LOGWARN (TEXT ("Couldn't set default socket options, error ") << ec); SetLastError (ec); return NULL; } if ((send (sock, "!", 1, 0) != 1) || fcntl (sock, F_SETFL, O_NONBLOCK)) { int ec = GetLastError (); close (sock); if (ec == EPIPE) { LOGWARN (TEXT ("Client disconnected before receiving handshake")); goto failedOperation; } LOGWARN (TEXT ("Couldn't send handshake message, error ") << ec); SetLastError (ec); return NULL; } else { LOGDEBUG (TEXT ("Handshake message written")); } return new CNamedPipe (sock, GetName (), false, IsReader ()); #endif }
void TskCarveExtractScalpel::carveFile(const std::string &unallocImgPath, const std::string &outputFolderPath, const std::string &stdOutFilePath, const std::string &stdErrFilePath) const { try { // Find out where Scalpel is installed. std::string scalpelDirPath = GetSystemProperty("SCALPEL_DIR"); if (scalpelDirPath.empty()) { throw TskException("TskCarveExtractScalpel::configure : Scalpel directory not set"); } if (!Poco::File(scalpelDirPath).exists()) { std::stringstream msg; msg << "TskCarveExtractScalpel::configure : specified Scalpel directory '" << scalpelDirPath << "' does not exist"; throw TskException(msg.str()); } // Get the path to the Scalpel executable. std::stringstream pathBuilder; pathBuilder << scalpelDirPath << Poco::Path::separator() << SCALPEL_EXE_FILE_NAME; std::string scalpelExePath = pathBuilder.str(); if (!Poco::File(scalpelExePath).exists()) { std::stringstream msg; msg << "TskCarveExtractScalpel::configure : Scalpel executable '" << scalpelExePath << "' does not exist"; throw TskException(msg.str()); } // Get the path to the Scalpel config file. std::string scalpelConfigFilePath = GetSystemProperty("SCALPEL_CONFIG_FILE"); if (!Poco::File(scalpelConfigFilePath).exists()) { std::stringstream msg; msg << "TskCarveExtractScalpel::TskCarveExtractScalpel : Scalpel config file '" << scalpelConfigFilePath << "' does not exist"; throw TskException(msg.str()); } // Set the Scalpel command line: specify the Scalpel config file. Poco::Process::Args args; args.push_back("-c"); args.push_back(scalpelConfigFilePath); // Set the Scalpel command line: allow for nested headers and footers. args.push_back("-e"); // Set the Scalpel command line: put any carved files directly into the output folder. args.push_back("-o"); args.push_back(outputFolderPath); args.push_back("-O"); // Set the Scalpel command line: specify the file to carve. args.push_back(unallocImgPath); // Launch Scalpel with console output redirects. Poco::Pipe outPipe; Poco::Pipe errPipe; Poco::ProcessHandle handle = Poco::Process::launch(scalpelExePath, args, NULL, &outPipe, &errPipe); // Capture the console output. Note that Scalpel may block at times as it waits for this loop to empty the stream buffers. Poco::PipeInputStream stdOutInputStream(outPipe); Poco::FileOutputStream stdOutOutputStream(stdOutFilePath); Poco::PipeInputStream stdErrInputStream(errPipe); Poco::FileOutputStream stdErrOutputStream(stdErrFilePath); while (stdOutInputStream || stdErrInputStream) { if (stdOutInputStream) { Poco::StreamCopier::copyStream(stdOutInputStream, stdOutOutputStream); } if (stdErrInputStream) { Poco::StreamCopier::copyStream(stdErrInputStream, stdErrOutputStream); } } // Scalpel should be finished since the console output streams are closed. int exitCode = Poco::Process::wait(handle); stdOutOutputStream.flush(); stdErrOutputStream.flush(); // On the first invocation of Scalpel, record its use in the image database. static bool toolInfoRecorded = false; if (!toolInfoRecorded) { std::ifstream stdOutStream(stdOutFilePath.c_str()); if (stdOutStream) { std::string versionString; std::getline(stdOutStream, versionString); Poco::StringTokenizer tokenizer(versionString, "\t ", Poco::StringTokenizer::TOK_IGNORE_EMPTY | Poco::StringTokenizer::TOK_TRIM); if (tokenizer[0] == "Scalpel" && tokenizer[1] == "version") { TskServices::Instance().getImgDB().addToolInfo("Scalpel", tokenizer[2].c_str()); toolInfoRecorded = true; } else { LOGWARN("TskCarveExtractScalpel::carveFile : Scalpel stdout output format changed, cannot record tool info"); } } else { LOGWARN("TskCarveExtractScalpel::carveFile : failed to open stdout stream, cannot record tool info"); } } // Delete input files by default. std::string option = GetSystemProperty("CARVE_EXTRACT_KEEP_INPUT_FILES"); std::transform(option.begin(), option.end(), option.begin(), ::toupper); bool deleteInputFiles = (option != "TRUE"); if (deleteInputFiles) { Poco::File file(unallocImgPath); file.remove(); } if (exitCode != 0) { std::stringstream msg; msg << "TskCarveExtractScalpel::carveFile : Scalpel exited with error exit code " << exitCode << " when carving '" << unallocImgPath.c_str() << "'"; throw TskException(msg.str()); } } catch (Poco::Exception &ex) { std::stringstream msg; msg << "TskCarveExtractScalpel::carveFile : Poco exception: " << ex.displayText(); throw TskException(msg.str()); } }