blob: 812bff8382daf17da5fc8846a503f1cafca6190f [file] [log] [blame]
// UpdatePair.cpp
#include "StdAfx.h"
#include <time.h>
#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<CArcItem> &arcItems,
NFileTimeType::EEnum fileTimeType,
CRecordVector<CUpdatePair> &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();
}