• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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