BOOL C4SDefinitions::AssertModules(const char *szPath, char *sMissing) { // Local only if (LocalOnly) return TRUE; // Check all listed modules for availability BOOL fAllAvailable=TRUE; char szModule[_MAX_PATH+1]; if (sMissing) sMissing[0]=0; // Check all definition files for (int32_t cnt=0; cnt<C4S_MaxDefinitions; cnt++) if (Definition[cnt][0]) { // Compose filename using path specified by caller szModule[0]=0; if (szPath) SCopy(szPath,szModule); if (szModule[0]) AppendBackslash(szModule); SAppend(Definition[cnt],szModule); // Missing if (!C4Group_IsGroup(szModule)) { // Add to list if (sMissing) { SNewSegment(sMissing,", "); SAppend(Definition[cnt],sMissing); } fAllAvailable=FALSE; } } return fAllAvailable; }
bool C4Group_ApplyUpdate(C4Group &hGroup) { // Process object update group (GRPUP_Entries.txt found) C4UpdatePackage Upd; if (hGroup.FindEntry(C4CFN_UpdateEntries)) if (Upd.Load(&hGroup)) { // Do update check first (ensure packet has everything it needs in order // to perfom the update) int iRes = Upd.Check(&hGroup); switch (iRes) { // Bad version - checks against version of the applying executable // (major version must match, minor version must be equal or higher) case C4UPD_CHK_BAD_VERSION: fprintf(stderr, "This update %s can only be applied using version " "%d.%d.%d.%d or higher.\n", Upd.Name, Upd.RequireVersion[0], Upd.RequireVersion[1], Upd.RequireVersion[2], Upd.RequireVersion[3]); return false; // Target not found: keep going case C4UPD_CHK_NO_SOURCE: fprintf(stderr, "Target %s for update %s not found. Ignoring.\n", Upd.DestPath, Upd.Name); return true; // Target mismatch: abort updating case C4UPD_CHK_BAD_SOURCE: fprintf(stderr, "Target %s incorrect version for update %s. Ignoring.\n", Upd.DestPath, Upd.Name); return true; // Target already updated: keep going case C4UPD_CHK_ALREADY_UPDATED: fprintf(stderr, "Target %s already up-to-date at %s.\n", Upd.DestPath, Upd.Name); return true; // Ok to perform update case C4UPD_CHK_OK: printf("Updating %s to %s... ", Upd.DestPath, Upd.Name); // Make sure the user sees the message while the work is in progress fflush(stdout); // Execute update if (Upd.Execute(&hGroup)) { printf("Ok\n"); return true; } else { printf("Failed\n"); return false; } // Unknown return value from update default: fprintf(stderr, "Unknown error while updating.\n"); return false; } } // Process binary update group (AutoUpdate.txt found, additional binary files // found) if (hGroup.EntryCount(C4CFN_UpdateCore)) if (hGroup.EntryCount() - hGroup.EntryCount(C4CFN_UpdateCore) - hGroup.EntryCount("*.c4u") > 0) { // Notice: AutoUpdate.txt is currently not processed... char strEntry[_MAX_FNAME + 1] = ""; StdStrBuf strList; printf("Updating binaries...\n"); hGroup.ResetSearch(); // Look for binaries while (hGroup.FindNextEntry("*", strEntry)) // Accept everything except *.c4u, AutoUpdate.txt, and c4group.exe // (which is assumed not to work under Windows) if (!WildcardMatch("*.c4u", strEntry) && !WildcardMatch(C4CFN_UpdateCore, strEntry) && !WildcardMatch("c4group.exe", strEntry)) { strList += strEntry; strList += ";"; } // Extract binaries to current working directory if (!hGroup.Extract(strList.getData())) return false; // If extracted file is a group, explode it (this is meant for Clonk.app // on Mac) for (int i = 0; SGetModule(strList.getData(), i, strEntry); i++) if (C4Group_IsGroup(strEntry)) { printf("Exploding: %s\n", strEntry); if (!C4Group_ExplodeDirectory(strEntry)) return false; } } // Process any child updates (*.c4u) if (hGroup.FindEntry("*.c4u")) { // Process all children char strEntry[_MAX_FNAME + 1] = ""; C4Group hChild; hGroup.ResetSearch(); while (hGroup.FindNextEntry("*.c4u", strEntry)) if (hChild.OpenAsChild(&hGroup, strEntry)) { bool ok = C4Group_ApplyUpdate(hChild); hChild.Close(); // Failure on child update if (!ok) return false; } } // Success return true; }
bool C4MainMenu::ActivateSavegame(int32_t iPlayer) { // Check if saving is possible if (!Game.CanQuickSave()) return false; // Menu symbol/init char DirPath[_MAX_PATH+1]; char ScenName[_MAX_PATH+1]; *ScenName=0; InitRefSym(GfxR->fctMenu.GetPhase(0), LoadResStr("IDS_MENU_CPSAVEGAME"), iPlayer); SetAlignment(C4MN_Align_Left | C4MN_Align_Bottom); SetPermanent(true); // target file name mask // get folder & filename to store in // some magic is needed to ensure savegames are stored properly into their folders SCopy(GetFilename(Game.ScenarioFilename), DirPath); if (DirPath[strlen(DirPath) - 1] == '\\') DirPath[strlen(DirPath) - 1] = 0; RemoveExtension(DirPath); if (LooksLikeInteger(DirPath)) { // ScenTitle.ocf\%d.ocs-names (old-style savegames) // get owning folder if (Game.pParentGroup) { // owning folder determines filename SCopy(GetFilenameOnly(Game.pParentGroup->GetName()), ScenName); } else { // no owning folder known: too bad // make a vague guess based on the scenario title SCopy(GetFilenameOnly(Game.ScenarioFilename), ScenName); } } else { // DirPath is a valid filename for now... SCopy(DirPath, ScenName); // but remove trailing numbers to adjust new-style savegames char *pScenNameEnd = ScenName+SLen(ScenName); while (Inside<char>(*--pScenNameEnd, '0', '9')) if (pScenNameEnd == ScenName) { // should not happen: digit-only-filenames should have been caught earlier SCopy("dbg_error!", ScenName); pScenNameEnd = ScenName+SLen(ScenName)-1; } pScenNameEnd[1]=0; } // New Style 2007: // * scenarios are saved into ScenName.ocf/ScenName123.ocs to keep umlauts out of filenames // * language titles are stored in folders as title component StdStrBuf strFilename, strTitle; strFilename.Format("%s.ocf%c%s%%d.ocs", ScenName, DirectorySeparator, ScenName); strTitle = Game.ScenarioTitle; // Create menu items StdStrBuf strFilenameIndexed, strCommand, strCaption, strSavePath; for (int32_t i = 1; i <= 10; i++) { // Index filename strFilenameIndexed.Format(strFilename.getData(), i); // Compose commmand strCommand.Format("Save:Game:%s:%s", strFilenameIndexed.getData(), strTitle.getData()); // Notice: the language title might contain ':' and thus confuse the segment list - but C4Menu::MenuCommand will try to handle this... // Check free slot strSavePath.Format("%s%c%s", Config.AtUserDataPath(C4CFN_Savegames), DirectorySeparator, strFilenameIndexed.getData()); bool fFree = !C4Group_IsGroup(strSavePath.getData()); // Item caption strCaption = LoadResStr("IDS_MENU_CPSAVEGAME"); // add menu item AddRefSym(strCaption.getData(), GfxR->fctMenu.GetPhase(i - 1, fFree ? 2 : 1), strCommand.getData(), C4MN_Item_NoCount, NULL, LoadResStr("IDS_MENU_CPSAVEGAMEINFO")); } // Go back to options menu on close SetCloseCommand("ActivateMenu:Main"); return true; }
bool C4Group_ApplyUpdate(C4Group &hGroup, unsigned long ParentProcessID) { // Wait for parent process to terminate (so we can safely replace the executable) #ifdef _WIN32 if(ParentProcessID) { HANDLE ParentProcess = OpenProcess(SYNCHRONIZE, FALSE, ParentProcessID); if(ParentProcess) { // If we couldn't find a handle then either // a) the process terminated already, which is great. // b) OpenProcess() failed, which is not so great. But let's still try to do // the update. printf("Waiting for parent process to terminate..."); DWORD res = WaitForSingleObject(ParentProcess, 10000); if(res == WAIT_TIMEOUT) fprintf(stderr, "Parent process did not terminate after 10 seconds. Continuing..."); } } #else // We could use waitpid on Unix, but we don't need that functionality there anyway... #endif // Process object update group (GRPUP_Entries.txt found) C4UpdatePackage Upd; if (hGroup.FindEntry(C4CFN_UpdateEntries)) if (Upd.Load(&hGroup)) { // Do update check first (ensure packet has everything it needs in order to perfom the update) int iRes = Upd.Check(&hGroup); switch (iRes) { // Bad version - checks against version of the applying executable (major version must match, minor version must be equal or higher) case C4UPD_CHK_BAD_VERSION: fprintf(stderr, "This update %s can only be applied using version %d.%d.%d.%d or higher.\n", Upd.Name, Upd.RequireVersion[0], Upd.RequireVersion[1], Upd.RequireVersion[2], Upd.RequireVersion[3]); return false; // Target not found: keep going case C4UPD_CHK_NO_SOURCE: fprintf(stderr, "Target %s for update %s not found. Ignoring.\n", Upd.DestPath, Upd.Name); return true; // Target mismatch: abort updating case C4UPD_CHK_BAD_SOURCE: fprintf(stderr, "Target %s incorrect version for update %s. Ignoring.\n", Upd.DestPath, Upd.Name); return true; // Target already updated: keep going case C4UPD_CHK_ALREADY_UPDATED: fprintf(stderr,"Target %s already up-to-date at %s.\n", Upd.DestPath, Upd.Name); return true; // Ok to perform update case C4UPD_CHK_OK: printf("Updating %s to %s... ", Upd.DestPath, Upd.Name); // Make sure the user sees the message while the work is in progress fflush(stdout); // Execute update if (Upd.Execute(&hGroup)) { printf("Ok\n"); return true; } else { printf("Failed\n"); return false; } // Unknown return value from update default: fprintf(stderr,"Unknown error while updating.\n"); return false; } } // Process binary update group (AutoUpdate.txt found, additional binary files found) if (hGroup.EntryCount(C4CFN_UpdateCore)) if (hGroup.EntryCount() - hGroup.EntryCount(C4CFN_UpdateCore) - hGroup.EntryCount("*.ocu") > 0) { // Notice: AutoUpdate.txt is currently not processed... char strEntry[_MAX_FNAME + 1] = ""; StdStrBuf strList; printf("Updating binaries...\n"); hGroup.ResetSearch(); // Look for binaries while (hGroup.FindNextEntry("*", strEntry)) // Accept everything except *.ocu, AutoUpdate.txt, and c4group.exe (which is assumed not to work under Windows) if (!WildcardMatch("*.ocu", strEntry) && !WildcardMatch(C4CFN_UpdateCore, strEntry) && !WildcardMatch("c4group.exe", strEntry)) { strList += strEntry; strList += ";"; } // Extract binaries to current working directory if (!hGroup.Extract(strList.getData())) return false; // If extracted file is a group, explode it (this is meant for Clonk.app on Mac) for (int i = 0; SGetModule(strList.getData(), i, strEntry); i++) if (C4Group_IsGroup(strEntry)) { printf("Exploding: %s\n", strEntry); if (!C4Group_ExplodeDirectory(strEntry)) return false; } } // Process any child updates (*.ocu) if (hGroup.FindEntry("*.ocu")) { // Process all children char strEntry[_MAX_FNAME + 1] = ""; C4Group hChild; hGroup.ResetSearch(); while (hGroup.FindNextEntry("*.ocu", strEntry)) if (hChild.OpenAsChild(&hGroup, strEntry)) { bool ok = C4Group_ApplyUpdate(hChild, 0); hChild.Close(); // Failure on child update if (!ok) return false; } } // Success return true; }