1baa3858d3f5d128a5c8466b700098109edcad5f2repo sync// UpdatePair.cpp
2baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
3baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "StdAfx.h"
4baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
5baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include <time.h>
6baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
7baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Common/Defs.h"
8baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Common/Wildcard.h"
9baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
10baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "Windows/Time.h"
11baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
12baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "SortUtils.h"
13baa3858d3f5d128a5c8466b700098109edcad5f2repo sync#include "UpdatePair.h"
14baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
15baa3858d3f5d128a5c8466b700098109edcad5f2repo syncusing namespace NWindows;
16baa3858d3f5d128a5c8466b700098109edcad5f2repo syncusing namespace NTime;
17baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
18baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time1, const FILETIME &time2)
19baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
20baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  switch(fileTimeType)
21baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
22baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case NFileTimeType::kWindows:
23baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      return ::CompareFileTime(&time1, &time2);
24baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case NFileTimeType::kUnix:
25baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
26baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        UInt32 unixTime1, unixTime2;
27baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        FileTimeToUnixTime(time1, unixTime1);
28baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        FileTimeToUnixTime(time2, unixTime2);
29baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return MyCompare(unixTime1, unixTime2);
30baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
31baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    case NFileTimeType::kDOS:
32baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
33baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        UInt32 dosTime1, dosTime2;
34baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        FileTimeToDosTime(time1, dosTime1);
35baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        FileTimeToDosTime(time2, dosTime2);
36baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        return MyCompare(dosTime1, dosTime2);
37baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
38baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
39baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  throw 4191618;
40baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
41baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
42baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const wchar_t *kDuplicateFileNameMessage = L"Duplicate filename:";
43baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic const wchar_t *kNotCensoredCollisionMessaged = L"Internal file name collision (file on disk, file in archive):";
44baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
45baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic void ThrowError(const UString &message, const UString &s1, const UString &s2)
46baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
47baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UString m = message;
48baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  m += L'\n';
49baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  m += s1;
50baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  m += L'\n';
51baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  m += s2;
52baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  throw m;
53baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
54baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
55baa3858d3f5d128a5c8466b700098109edcad5f2repo syncstatic void TestDuplicateString(const UStringVector &strings, const CIntVector &indices)
56baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
57baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for(int i = 0; i + 1 < indices.Size(); i++)
58baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (CompareFileNames(strings[indices[i]], strings[indices[i + 1]]) == 0)
59baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      ThrowError(kDuplicateFileNameMessage, strings[indices[i]], strings[indices[i + 1]]);
60baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
61baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
62baa3858d3f5d128a5c8466b700098109edcad5f2repo syncvoid GetUpdatePairInfoList(
63baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const CDirItems &dirItems,
64baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const CObjectVector<CArcItem> &arcItems,
65baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    NFileTimeType::EEnum fileTimeType,
66baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CRecordVector<CUpdatePair> &updatePairs)
67baa3858d3f5d128a5c8466b700098109edcad5f2repo sync{
68baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  CIntVector dirIndices, arcIndices;
69baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
70baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  int numDirItems = dirItems.Items.Size();
71baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  int numArcItems = arcItems.Size();
72baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
73baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
74baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
75baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    UStringVector arcNames;
76baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    arcNames.Reserve(numArcItems);
77baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (int i = 0; i < numArcItems; i++)
78baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      arcNames.Add(arcItems[i].Name);
79baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    SortFileNames(arcNames, arcIndices);
80baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    TestDuplicateString(arcNames, arcIndices);
81baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
82baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
83baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  UStringVector dirNames;
84baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
85baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    dirNames.Reserve(numDirItems);
86baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    for (int i = 0; i < numDirItems; i++)
87baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      dirNames.Add(dirItems.GetLogPath(i));
88baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    SortFileNames(dirNames, dirIndices);
89baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    TestDuplicateString(dirNames, dirIndices);
90baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
91baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
92baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  int dirIndex = 0, arcIndex = 0;
93baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  while (dirIndex < numDirItems && arcIndex < numArcItems)
94baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
95baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CUpdatePair pair;
96baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int dirIndex2 = dirIndices[dirIndex];
97baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int arcIndex2 = arcIndices[arcIndex];
98baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const CDirItem &di = dirItems.Items[dirIndex2];
99baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    const CArcItem &ai = arcItems[arcIndex2];
100baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int compareResult = CompareFileNames(dirNames[dirIndex2], ai.Name);
101baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    if (compareResult < 0)
102baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
103baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      pair.State = NUpdateArchive::NPairState::kOnlyOnDisk;
104baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      pair.DirIndex = dirIndex2;
105baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      dirIndex++;
106baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
107baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    else if (compareResult > 0)
108baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
109baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      pair.State = ai.Censored ?
110baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          NUpdateArchive::NPairState::kOnlyInArchive:
111baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          NUpdateArchive::NPairState::kNotMasked;
112baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      pair.ArcIndex = arcIndex2;
113baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      arcIndex++;
114baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
115baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    else
116baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    {
117baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      if (!ai.Censored)
118baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        ThrowError(kNotCensoredCollisionMessaged, dirNames[dirIndex2], ai.Name);
119baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      pair.DirIndex = dirIndex2;
120baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      pair.ArcIndex = arcIndex2;
121baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      switch (ai.MTimeDefined ? MyCompareTime(
122baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          ai.TimeType != - 1 ? (NFileTimeType::EEnum)ai.TimeType : fileTimeType,
123baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          di.MTime, ai.MTime): 0)
124baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      {
125baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break;
126baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        case 1:  pair.State = NUpdateArchive::NPairState::kOldInArchive; break;
127baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        default:
128baa3858d3f5d128a5c8466b700098109edcad5f2repo sync          pair.State = (ai.SizeDefined && di.Size == ai.Size) ?
129baa3858d3f5d128a5c8466b700098109edcad5f2repo sync              NUpdateArchive::NPairState::kSameFiles :
130baa3858d3f5d128a5c8466b700098109edcad5f2repo sync              NUpdateArchive::NPairState::kUnknowNewerFiles;
131baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      }
132baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      dirIndex++;
133baa3858d3f5d128a5c8466b700098109edcad5f2repo sync      arcIndex++;
134baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    }
135baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    updatePairs.Add(pair);
136baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
137baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
138baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (; dirIndex < numDirItems; dirIndex++)
139baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
140baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CUpdatePair pair;
141baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    pair.State = NUpdateArchive::NPairState::kOnlyOnDisk;
142baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    pair.DirIndex = dirIndices[dirIndex];
143baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    updatePairs.Add(pair);
144baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
145baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
146baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  for (; arcIndex < numArcItems; arcIndex++)
147baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  {
148baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    CUpdatePair pair;
149baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    int arcIndex2 = arcIndices[arcIndex];
150baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    pair.State = arcItems[arcIndex2].Censored ?
151baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        NUpdateArchive::NPairState::kOnlyInArchive:
152baa3858d3f5d128a5c8466b700098109edcad5f2repo sync        NUpdateArchive::NPairState::kNotMasked;
153baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    pair.ArcIndex = arcIndex2;
154baa3858d3f5d128a5c8466b700098109edcad5f2repo sync    updatePairs.Add(pair);
155baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  }
156baa3858d3f5d128a5c8466b700098109edcad5f2repo sync
157baa3858d3f5d128a5c8466b700098109edcad5f2repo sync  updatePairs.ReserveDown();
158baa3858d3f5d128a5c8466b700098109edcad5f2repo sync}
159