tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

UpdatePair.cpp (6508B)


      1 // UpdatePair.cpp
      2 
      3 #include "StdAfx.h"
      4 
      5 #include <time.h>
      6 
      7 #include "../../../Common/Wildcard.h"
      8 
      9 #include "../../../Windows/TimeUtils.h"
     10 
     11 #include "SortUtils.h"
     12 #include "UpdatePair.h"
     13 
     14 using namespace NWindows;
     15 using namespace NTime;
     16 
     17 static int MyCompareTime(NFileTimeType::EEnum fileTimeType, const FILETIME &time1, const FILETIME &time2)
     18 {
     19  switch (fileTimeType)
     20  {
     21    case NFileTimeType::kWindows:
     22      return ::CompareFileTime(&time1, &time2);
     23    case NFileTimeType::kUnix:
     24      {
     25        UInt32 unixTime1, unixTime2;
     26        FileTimeToUnixTime(time1, unixTime1);
     27        FileTimeToUnixTime(time2, unixTime2);
     28        return MyCompare(unixTime1, unixTime2);
     29      }
     30    case NFileTimeType::kDOS:
     31      {
     32        UInt32 dosTime1, dosTime2;
     33        FileTimeToDosTime(time1, dosTime1);
     34        FileTimeToDosTime(time2, dosTime2);
     35        return MyCompare(dosTime1, dosTime2);
     36      }
     37  }
     38  throw 4191618;
     39 }
     40 
     41 static const char * const k_Duplicate_inArc_Message = "Duplicate filename in archive:";
     42 static const char * const k_Duplicate_inDir_Message = "Duplicate filename on disk:";
     43 static const char * const k_NotCensoredCollision_Message = "Internal file name collision (file on disk, file in archive):";
     44 
     45 static void ThrowError(const char *message, const UString &s1, const UString &s2)
     46 {
     47  UString m (message);
     48  m.Add_LF(); m += s1;
     49  m.Add_LF(); m += s2;
     50  throw m;
     51 }
     52 
     53 static int CompareArcItemsBase(const CArcItem &ai1, const CArcItem &ai2)
     54 {
     55  int res = CompareFileNames(ai1.Name, ai2.Name);
     56  if (res != 0)
     57    return res;
     58  if (ai1.IsDir != ai2.IsDir)
     59    return ai1.IsDir ? -1 : 1;
     60  return 0;
     61 }
     62 
     63 static int CompareArcItems(const unsigned *p1, const unsigned *p2, void *param)
     64 {
     65  unsigned i1 = *p1;
     66  unsigned i2 = *p2;
     67  const CObjectVector<CArcItem> &arcItems = *(const CObjectVector<CArcItem> *)param;
     68  int res = CompareArcItemsBase(arcItems[i1], arcItems[i2]);
     69  if (res != 0)
     70    return res;
     71  return MyCompare(i1, i2);
     72 }
     73 
     74 void GetUpdatePairInfoList(
     75    const CDirItems &dirItems,
     76    const CObjectVector<CArcItem> &arcItems,
     77    NFileTimeType::EEnum fileTimeType,
     78    CRecordVector<CUpdatePair> &updatePairs)
     79 {
     80  CUIntVector dirIndices, arcIndices;
     81  
     82  unsigned numDirItems = dirItems.Items.Size();
     83  unsigned numArcItems = arcItems.Size();
     84  
     85  CIntArr duplicatedArcItem(numArcItems);
     86  {
     87    int *vals = &duplicatedArcItem[0];
     88    for (unsigned i = 0; i < numArcItems; i++)
     89      vals[i] = 0;
     90  }
     91 
     92  {
     93    arcIndices.ClearAndSetSize(numArcItems);
     94    if (numArcItems != 0)
     95    {
     96      unsigned *vals = &arcIndices[0];
     97      for (unsigned i = 0; i < numArcItems; i++)
     98        vals[i] = i;
     99    }
    100    arcIndices.Sort(CompareArcItems, (void *)&arcItems);
    101    for (unsigned i = 0; i + 1 < numArcItems; i++)
    102      if (CompareArcItemsBase(
    103          arcItems[arcIndices[i]],
    104          arcItems[arcIndices[i + 1]]) == 0)
    105      {
    106        duplicatedArcItem[i] = 1;
    107        duplicatedArcItem[i + 1] = -1;
    108      }
    109  }
    110 
    111  UStringVector dirNames;
    112  {
    113    dirNames.ClearAndReserve(numDirItems);
    114    unsigned i;
    115    for (i = 0; i < numDirItems; i++)
    116      dirNames.AddInReserved(dirItems.GetLogPath(i));
    117    SortFileNames(dirNames, dirIndices);
    118    for (i = 0; i + 1 < numDirItems; i++)
    119    {
    120      const UString &s1 = dirNames[dirIndices[i]];
    121      const UString &s2 = dirNames[dirIndices[i + 1]];
    122      if (CompareFileNames(s1, s2) == 0)
    123        ThrowError(k_Duplicate_inDir_Message, s1, s2);
    124    }
    125  }
    126  
    127  unsigned dirIndex = 0;
    128  unsigned arcIndex = 0;
    129 
    130  int prevHostFile = -1;
    131  const UString *prevHostName = NULL;
    132  
    133  while (dirIndex < numDirItems || arcIndex < numArcItems)
    134  {
    135    CUpdatePair pair;
    136    
    137    int dirIndex2 = -1;
    138    int arcIndex2 = -1;
    139    const CDirItem *di = NULL;
    140    const CArcItem *ai = NULL;
    141    
    142    int compareResult = -1;
    143    const UString *name = NULL;
    144    
    145    if (dirIndex < numDirItems)
    146    {
    147      dirIndex2 = dirIndices[dirIndex];
    148      di = &dirItems.Items[dirIndex2];
    149    }
    150 
    151    if (arcIndex < numArcItems)
    152    {
    153      arcIndex2 = arcIndices[arcIndex];
    154      ai = &arcItems[arcIndex2];
    155      compareResult = 1;
    156      if (dirIndex < numDirItems)
    157      {
    158        compareResult = CompareFileNames(dirNames[dirIndex2], ai->Name);
    159        if (compareResult == 0)
    160        {
    161          if (di->IsDir() != ai->IsDir)
    162            compareResult = (ai->IsDir ? 1 : -1);
    163        }
    164      }
    165    }
    166    
    167    if (compareResult < 0)
    168    {
    169      name = &dirNames[dirIndex2];
    170      pair.State = NUpdateArchive::NPairState::kOnlyOnDisk;
    171      pair.DirIndex = dirIndex2;
    172      dirIndex++;
    173    }
    174    else if (compareResult > 0)
    175    {
    176      name = &ai->Name;
    177      pair.State = ai->Censored ?
    178          NUpdateArchive::NPairState::kOnlyInArchive:
    179          NUpdateArchive::NPairState::kNotMasked;
    180      pair.ArcIndex = arcIndex2;
    181      arcIndex++;
    182    }
    183    else
    184    {
    185      int dupl = duplicatedArcItem[arcIndex];
    186      if (dupl != 0)
    187        ThrowError(k_Duplicate_inArc_Message, ai->Name, arcItems[arcIndices[arcIndex + dupl]].Name);
    188 
    189      name = &dirNames[dirIndex2];
    190      if (!ai->Censored)
    191        ThrowError(k_NotCensoredCollision_Message, *name, ai->Name);
    192      
    193      pair.DirIndex = dirIndex2;
    194      pair.ArcIndex = arcIndex2;
    195 
    196      switch (ai->MTimeDefined ? MyCompareTime(
    197          ai->TimeType != - 1 ? (NFileTimeType::EEnum)ai->TimeType : fileTimeType,
    198          di->MTime, ai->MTime): 0)
    199      {
    200        case -1: pair.State = NUpdateArchive::NPairState::kNewInArchive; break;
    201        case  1: pair.State = NUpdateArchive::NPairState::kOldInArchive; break;
    202        default:
    203          pair.State = (ai->SizeDefined && di->Size == ai->Size) ?
    204              NUpdateArchive::NPairState::kSameFiles :
    205              NUpdateArchive::NPairState::kUnknowNewerFiles;
    206      }
    207      
    208      dirIndex++;
    209      arcIndex++;
    210    }
    211    
    212    if ((di && di->IsAltStream) ||
    213        (ai && ai->IsAltStream))
    214    {
    215      if (prevHostName)
    216      {
    217        unsigned hostLen = prevHostName->Len();
    218        if (name->Len() > hostLen)
    219          if ((*name)[hostLen] == ':' && CompareFileNames(*prevHostName, name->Left(hostLen)) == 0)
    220            pair.HostIndex = prevHostFile;
    221      }
    222    }
    223    else
    224    {
    225      prevHostFile = updatePairs.Size();
    226      prevHostName = name;
    227    }
    228    
    229    updatePairs.Add(pair);
    230  }
    231 
    232  updatePairs.ReserveDown();
    233 }