Home | History | Annotate | Download | only in Common
      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 
     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 
     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 
     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 
     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