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