BOOL C4UpdatePackage::Optimize(C4Group *pGrpFrom, C4GroupEx *pGrpTo, const char *strFileName) { // group file? C4Group ItemGroupFrom; if (!ItemGroupFrom.OpenAsChild(pGrpFrom, strFileName)) return TRUE; // try to open target group C4GroupEx ItemGroupTo; char strTempGroup[_MAX_PATH + 1]; strTempGroup[0] = 0; if (!ItemGroupTo.OpenAsChild(pGrpTo, strFileName)) return TRUE; // update children char ItemFileName[_MAX_PATH]; ItemGroupFrom.ResetSearch(); while (ItemGroupFrom.FindNextEntry("*", ItemFileName)) Optimize(&ItemGroupFrom, &ItemGroupTo, ItemFileName); // set head if (ItemGroupTo.HeadIdentical(ItemGroupFrom, true)) ItemGroupTo.SetHead(ItemGroupFrom); // write group (do not change any headers set by DoGrpUpdate!) ItemGroupTo.Close(FALSE); // set core (C4Group::Save overwrites it) pGrpTo->SaveEntryCore(*pGrpFrom, strFileName); pGrpTo->SetSavedEntryCore(strFileName); return TRUE; }
bool C4UpdatePackage::DoUpdate(C4Group *pGrpFrom, C4GroupEx *pGrpTo, const char *strFileName) { // group file? C4Group ItemGroupFrom; if (ItemGroupFrom.OpenAsChild(pGrpFrom, strFileName)) { // try to open target group C4GroupEx ItemGroupTo; char strTempGroup[_MAX_PATH+1]; strTempGroup[0] = 0; if (!ItemGroupTo.OpenAsChild(pGrpTo, strFileName, false, true)) return false; // update children char ItemFileName[_MAX_PATH]; ItemGroupFrom.ResetSearch(); while (ItemGroupFrom.FindNextEntry("*", ItemFileName)) if (!SEqual(ItemFileName, C4CFN_UpdateCore) && !SEqual(ItemFileName, C4CFN_UpdateEntries)) DoUpdate(&ItemGroupFrom, &ItemGroupTo, ItemFileName); if (GrpUpdate) { DoGrpUpdate(&ItemGroupFrom, &ItemGroupTo); // write group (do not change any headers set by DoGrpUpdate!) ItemGroupTo.Close(false); // set core (C4Group::Save overwrites it) pGrpTo->SaveEntryCore(*pGrpFrom, strFileName); pGrpTo->SetSavedEntryCore(strFileName); // flag as no-resort pGrpTo->SetNoSort(strFileName); } else { // write group ItemGroupTo.Close(true); // temporary group? if (strTempGroup[0]) if (!pGrpTo->Move(strTempGroup, strFileName)) return false; } } else { #ifdef _WIN32 OutputDebugString(FormatString("updating %s\\%s\n", pGrpTo->GetFullName().getData(), strFileName).GetWideChar()); #elif defined(_DEBUG) printf("updating %s\\%s\n", pGrpTo->GetFullName().getData(), strFileName); #endif if (!C4Group_CopyEntry(pGrpFrom, pGrpTo, strFileName)) return false; // set core pGrpTo->SaveEntryCore(*pGrpFrom, strFileName); pGrpTo->SetSavedEntryCore(strFileName); } // ok return true; }
BOOL C4UpdatePackage::MkUp(C4Group *pGrp1, C4Group *pGrp2, C4GroupEx *pUpGrp, BOOL *fModified) { // (CAUTION: pGrp1 may be NULL - that means that there is no counterpart for // Grp2 // in the base group) // compare headers if (!pGrp1 || pGrp1->GetCreation() != pGrp2->GetCreation() || pGrp1->GetOriginal() != pGrp2->GetOriginal() || !SEqual(pGrp1->GetMaker(), pGrp2->GetMaker()) || !SEqual(pGrp1->GetPassword(), pGrp2->GetPassword())) *fModified = TRUE; // set header pUpGrp->SetHead(*pGrp2); // compare entries char strItemName[_MAX_PATH], strItemName2[_MAX_PATH]; StdStrBuf EntryList; strItemName[0] = strItemName2[0] = 0; pGrp2->ResetSearch(); if (!*fModified) pGrp1->ResetSearch(); int iChangedEntries = 0; while (pGrp2->FindNextEntry("*", strItemName, NULL, NULL, !!strItemName[0])) { // add to entry list if (!!EntryList) EntryList.AppendChar('|'); EntryList.AppendFormat("%s=%d", strItemName, pGrp2->EntryTime(strItemName)); // no modification detected yet? then check order if (!*fModified) { if (!pGrp1->FindNextEntry("*", strItemName2, NULL, NULL, !!strItemName2[0])) *fModified = TRUE; else if (!SEqual(strItemName, strItemName2)) *fModified = TRUE; } // TODO: write DeleteEntries.txt // a child group? C4GroupEx ChildGrp2; if (ChildGrp2.OpenAsChild(pGrp2, strItemName)) { // open in Grp1 C4Group *pChildGrp1 = new C4GroupEx(); if (!pGrp1 || !pChildGrp1->OpenAsChild(pGrp1, strItemName)) { delete pChildGrp1; pChildGrp1 = NULL; } // open group for update data C4GroupEx UpdGroup; char strTempGroupName[_MAX_FNAME + 1]; strTempGroupName[0] = 0; if (!UpdGroup.OpenAsChild(pUpGrp, strItemName)) { // create new group (may be temporary) // SCopy(GetCfg()->AtTempPath("~upd"), strTempGroupName, _MAX_FNAME); MakeTempFilename(strTempGroupName); if (!UpdGroup.Open(strTempGroupName, TRUE)) { delete pChildGrp1; WriteLog("Error: could not create temp group\n"); return FALSE; } } // do nested MkUp-search BOOL Modified = FALSE; BOOL fSuccess = MkUp(pChildGrp1, &ChildGrp2, &UpdGroup, &Modified); // sort & close extern const char **C4Group_SortList; UpdGroup.SortByList(C4Group_SortList, ChildGrp2.GetName()); UpdGroup.Close(FALSE); // check entry times if (!pGrp1 || (pGrp1->EntryTime(strItemName) != pGrp2->EntryTime(strItemName))) Modified = TRUE; // add group (if modified) if (fSuccess && Modified) { if (strTempGroupName[0]) if (!pUpGrp->Move(strTempGroupName, strItemName)) { WriteLog("Error: could not add modified group\n"); return FALSE; } // copy core pUpGrp->SaveEntryCore(*pGrp2, strItemName); pUpGrp->SetSavedEntryCore(strItemName); // got a modification in a subgroup *fModified = TRUE; iChangedEntries++; } else // delete group (do not remove groups that existed before!) if (strTempGroupName[0]) if (remove(strTempGroupName)) if (rmdir(strTempGroupName)) { WriteLog("Error: could not delete temporary directory\n"); return FALSE; } delete pChildGrp1; } else { // compare them (size & crc32) if (!pGrp1 || pGrp1->EntrySize(strItemName) != pGrp2->EntrySize(strItemName) || pGrp1->EntryCRC32(strItemName) != pGrp2->EntryCRC32(strItemName)) { BOOL fCopied = FALSE; // save core (EntryCRC32 might set additional fields) pUpGrp->SaveEntryCore(*pGrp2, strItemName); // already in update grp? if (pUpGrp->EntryTime(strItemName) != pGrp2->EntryTime(strItemName) || pUpGrp->EntrySize(strItemName) != pGrp2->EntrySize(strItemName) || pUpGrp->EntryCRC32(strItemName) != pGrp2->EntryCRC32(strItemName)) { // copy it if (!C4Group_CopyEntry(pGrp2, pUpGrp, strItemName)) { WriteLog("Error: could not add changed entry to update group\n"); return FALSE; } // set entry core pUpGrp->SetSavedEntryCore(strItemName); // modified... *fModified = TRUE; fCopied = TRUE; } iChangedEntries++; WriteLog("%s\\%s: update%s\n", pGrp2->GetFullName().getData(), strItemName, fCopied ? "" : " (already in group)"); } } } // write entries list (always) if (!pUpGrp->Add(C4CFN_UpdateEntries, EntryList, FALSE, TRUE)) { WriteLog("Error: could not save entry list!"); return FALSE; } if (iChangedEntries > 0) WriteLog("%s: %d/%d changed (%s)\n", pGrp2->GetFullName().getData(), iChangedEntries, pGrp2->EntryCount(), *fModified ? "update" : "skip"); // success return TRUE; }
BOOL C4UpdatePackage::DoUpdate(C4Group *pGrpFrom, C4GroupEx *pGrpTo, const char *strFileName) { // group file? C4Group ItemGroupFrom; if (ItemGroupFrom.OpenAsChild(pGrpFrom, strFileName)) { // try to open target group C4GroupEx ItemGroupTo; char strTempGroup[_MAX_PATH + 1]; strTempGroup[0] = 0; if (!ItemGroupTo.OpenAsChild(pGrpTo, strFileName)) { // create (emtpy) temp dir // SCopy(GetCfg()->AtExePath("~tmp"), strTempGroup, //_MAX_PATH); MakeTempFilename(strTempGroup); // open/create it if (!ItemGroupTo.Open(strTempGroup, TRUE)) return FALSE; } // update children char ItemFileName[_MAX_PATH]; ItemGroupFrom.ResetSearch(); while (ItemGroupFrom.FindNextEntry("*", ItemFileName)) if (!SEqual(ItemFileName, C4CFN_UpdateCore) && !SEqual(ItemFileName, C4CFN_UpdateEntries)) DoUpdate(&ItemGroupFrom, &ItemGroupTo, ItemFileName); // set maker (always) ItemGroupTo.SetMaker(ItemGroupFrom.GetMaker()); if (GrpUpdate) { DoGrpUpdate(&ItemGroupFrom, &ItemGroupTo); // write group (do not change any headers set by DoGrpUpdate!) ItemGroupTo.Close(FALSE); // temporary group? if (strTempGroup[0]) if (!pGrpTo->Move(strTempGroup, strFileName)) return FALSE; // set core (C4Group::Save overwrites it) pGrpTo->SaveEntryCore(*pGrpFrom, strFileName); pGrpTo->SetSavedEntryCore(strFileName); // flag as no-resort pGrpTo->SetNoSort(strFileName); } else { // write group ItemGroupTo.Close(TRUE); // temporary group? if (strTempGroup[0]) if (!pGrpTo->Move(strTempGroup, strFileName)) return FALSE; } } else { char strMsg[1024]; sprintf(strMsg, "updating %s\\%s\n", pGrpTo->GetFullName().getData(), strFileName); #ifdef _MSC_VER OutputDebugString(strMsg); #elif _DEBUG puts(strMsg); #endif if (!C4Group_CopyEntry(pGrpFrom, pGrpTo, strFileName)) return FALSE; // set core pGrpTo->SaveEntryCore(*pGrpFrom, strFileName); pGrpTo->SetSavedEntryCore(strFileName); } // ok return TRUE; }