// UpdatePair.cpp #include "StdAfx.h" #include #include "Common/Defs.h" #include "Common/Wildcard.h" #include "Windows/Time.h" #include "SortUtils.h" #include "UpdatePair.h" using namespace NWindows; using namespace NTime; static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time1, const FILETIME &time2) { switch(fileTimeType) { case NFileTimeType::kWindows: return ::CompareFileTime(&time1, &time2); case NFileTimeType::kUnix: { UInt32 unixTime1, unixTime2; FileTimeToUnixTime(time1, unixTime1); FileTimeToUnixTime(time2, unixTime2); return MyCompare(unixTime1, unixTime2); } case NFileTimeType::kDOS: { UInt32 dosTime1, dosTime2; FileTimeToDosTime(time1, dosTime1); FileTimeToDosTime(time2, dosTime2); return MyCompare(dosTime1, dosTime2); } } throw 4191618; } static const wchar_t *kDuplicateFileNameMessage = L"Duplicate filename:"; static const wchar_t *kNotCensoredCollisionMessaged = L"Internal file name collision (file on disk, file in archive):"; static void ThrowError(const UString &message, const UString &s1, const UString &s2) { UString m = message; m += L'\n'; m += s1; m += L'\n'; m += s2; throw m; } static void TestDuplicateString(const UStringVector &strings, const CIntVector &indices) { for(int i = 0; i + 1 < indices.Size(); i++) if (CompareFileNames(strings[indices[i]], strings[indices[i + 1]]) == 0) ThrowError(kDuplicateFileNameMessage, strings[indices[i]], strings[indices[i + 1]]); } void GetUpdatePairInfoList( const CDirItems &dirItems, const CObjectVector &arcItems, NFileTimeType::EEnum fileTimeType, CRecordVector &updatePairs) { CIntVector dirIndices, arcIndices; int numDirItems = dirItems.Items.Size(); int numArcItems = arcItems.Size(); { UStringVector arcNames; arcNames.Reserve(numArcItems); for (int i = 0; i < numArcItems; i++) arcNames.Add(arcItems[i].Name); SortFileNames(arcNames, arcIndices); TestDuplicateString(arcNames, arcIndices); } UStringVector dirNames; { dirNames.Reserve(numDirItems); for (int i = 0; i < numDirItems; i++) dirNames.Add(dirItems.GetLogPath(i)); SortFileNames(dirNames, dirIndices); TestDuplicateString(dirNames, dirIndices); } int dirIndex = 0, arcIndex = 0; while (dirIndex < numDirItems && arcIndex < numArcItems) { CUpdatePair pair; int dirIndex2 = dirIndices[dirIndex]; int arcIndex2 = arcIndices[arcIndex]; const CDirItem &di = dirItems.Items[dirIndex2]; const CArcItem &ai = arcItems[arcIndex2]; int compareResult = CompareFileNames(dirNames[dirIndex2], ai.Name); if (compareResult < 0) { pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; pair.DirIndex = dirIndex2; dirIndex++; } else if (compareResult > 0) { pair.State = ai.Censored ? NUpdateArchive::NPairState::kOnlyInArchive: NUpdateArchive::NPairState::kNotMasked; pair.ArcIndex = arcIndex2; arcIndex++; } else { if (!ai.Censored) ThrowError(kNotCensoredCollisionMessaged, dirNames[dirIndex2], ai.Name); pair.DirIndex = dirIndex2; pair.ArcIndex = arcIndex2; switch (ai.MTimeDefined ? MyCompareTime( ai.TimeType != - 1 ? (NFileTimeType::EEnum)ai.TimeType : fileTimeType, di.MTime, ai.MTime): 0) { case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break; case 1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break; default: pair.State = (ai.SizeDefined && di.Size == ai.Size) ? NUpdateArchive::NPairState::kSameFiles : NUpdateArchive::NPairState::kUnknowNewerFiles; } dirIndex++; arcIndex++; } updatePairs.Add(pair); } for (; dirIndex < numDirItems; dirIndex++) { CUpdatePair pair; pair.State = NUpdateArchive::NPairState::kOnlyOnDisk; pair.DirIndex = dirIndices[dirIndex]; updatePairs.Add(pair); } for (; arcIndex < numArcItems; arcIndex++) { CUpdatePair pair; int arcIndex2 = arcIndices[arcIndex]; pair.State = arcItems[arcIndex2].Censored ? NUpdateArchive::NPairState::kOnlyInArchive: NUpdateArchive::NPairState::kNotMasked; pair.ArcIndex = arcIndex2; updatePairs.Add(pair); } updatePairs.ReserveDown(); }