1 // DirItem.h 2 3 #ifndef ZIP7_INC_DIR_ITEM_H 4 #define ZIP7_INC_DIR_ITEM_H 5 6 #ifdef _WIN32 7 #include "../../../Common/MyLinux.h" 8 #endif 9 10 #include "../../../Common/MyString.h" 11 12 #include "../../../Windows/FileFind.h" 13 #include "../../../Windows/PropVariant.h" 14 #include "../../../Windows/TimeUtils.h" 15 16 #include "../../Common/UniqBlocks.h" 17 18 #include "../../Archive/IArchive.h" 19 20 struct CDirItemsStat 21 { 22 UInt64 NumDirs; 23 UInt64 NumFiles; 24 UInt64 NumAltStreams; 25 UInt64 FilesSize; 26 UInt64 AltStreamsSize; 27 28 UInt64 NumErrors; 29 30 // UInt64 Get_NumItems() const { return NumDirs + NumFiles + NumAltStreams; } Get_NumDataItemsCDirItemsStat31 UInt64 Get_NumDataItems() const { return NumFiles + NumAltStreams; } GetTotalBytesCDirItemsStat32 UInt64 GetTotalBytes() const { return FilesSize + AltStreamsSize; } 33 IsEmptyCDirItemsStat34 bool IsEmpty() const { return 35 0 == NumDirs 36 && 0 == NumFiles 37 && 0 == NumAltStreams 38 && 0 == FilesSize 39 && 0 == AltStreamsSize 40 && 0 == NumErrors; } 41 CDirItemsStatCDirItemsStat42 CDirItemsStat(): 43 NumDirs(0), 44 NumFiles(0), 45 NumAltStreams(0), 46 FilesSize(0), 47 AltStreamsSize(0), 48 NumErrors(0) 49 {} 50 }; 51 52 53 struct CDirItemsStat2: public CDirItemsStat 54 { 55 UInt64 Anti_NumDirs; 56 UInt64 Anti_NumFiles; 57 UInt64 Anti_NumAltStreams; 58 59 // UInt64 Get_NumItems() const { return Anti_NumDirs + Anti_NumFiles + Anti_NumAltStreams + CDirItemsStat::Get_NumItems(); } Get_NumDataItems2CDirItemsStat260 UInt64 Get_NumDataItems2() const { return Anti_NumFiles + Anti_NumAltStreams + CDirItemsStat::Get_NumDataItems(); } 61 IsEmptyCDirItemsStat262 bool IsEmpty() const { return CDirItemsStat::IsEmpty() 63 && 0 == Anti_NumDirs 64 && 0 == Anti_NumFiles 65 && 0 == Anti_NumAltStreams; } 66 CDirItemsStat2CDirItemsStat267 CDirItemsStat2(): 68 Anti_NumDirs(0), 69 Anti_NumFiles(0), 70 Anti_NumAltStreams(0) 71 {} 72 }; 73 74 75 Z7_PURE_INTERFACES_BEGIN 76 77 #define Z7_IFACEN_IDirItemsCallback(x) \ 78 virtual HRESULT ScanError(const FString &path, DWORD systemError) x \ 79 virtual HRESULT ScanProgress(const CDirItemsStat &st, const FString &path, bool isDir) x \ 80 81 Z7_IFACE_DECL_PURE(IDirItemsCallback) 82 83 Z7_PURE_INTERFACES_END 84 85 86 struct CArcTime 87 { 88 FILETIME FT; 89 UInt16 Prec; 90 Byte Ns100; 91 bool Def; 92 CArcTimeCArcTime93 CArcTime() 94 { 95 Clear(); 96 } 97 ClearCArcTime98 void Clear() 99 { 100 FT.dwHighDateTime = FT.dwLowDateTime = 0; 101 Prec = 0; 102 Ns100 = 0; 103 Def = false; 104 } 105 IsZeroCArcTime106 bool IsZero() const 107 { 108 return FT.dwLowDateTime == 0 && FT.dwHighDateTime == 0 && Ns100 == 0; 109 } 110 CompareWithCArcTime111 int CompareWith(const CArcTime &a) const 112 { 113 const int res = CompareFileTime(&FT, &a.FT); 114 if (res != 0) 115 return res; 116 if (Ns100 < a.Ns100) return -1; 117 if (Ns100 > a.Ns100) return 1; 118 return 0; 119 } 120 Get_FILETIME_as_UInt64CArcTime121 UInt64 Get_FILETIME_as_UInt64() const 122 { 123 return (((UInt64)FT.dwHighDateTime) << 32) + FT.dwLowDateTime; 124 } 125 Get_DosTimeCArcTime126 UInt32 Get_DosTime() const 127 { 128 FILETIME ft2 = FT; 129 if ((Prec == k_PropVar_TimePrec_Base + 8 || 130 Prec == k_PropVar_TimePrec_Base + 9) 131 && Ns100 != 0) 132 { 133 UInt64 u64 = Get_FILETIME_as_UInt64(); 134 // we round up even small (ns < 100ns) as FileTimeToDosTime() 135 if (u64 % 20000000 == 0) 136 { 137 u64++; 138 ft2.dwHighDateTime = (DWORD)(u64 >> 32); 139 ft2.dwHighDateTime = (DWORD)u64; 140 } 141 } 142 // FileTimeToDosTime() is expected to round up in Windows 143 UInt32 dosTime; 144 // we use simplified code with utctime->dos. 145 // do we need local time instead here? 146 NWindows::NTime::FileTime_To_DosTime(ft2, dosTime); 147 return dosTime; 148 } 149 GetNumDigitsCArcTime150 int GetNumDigits() const 151 { 152 if (Prec == k_PropVar_TimePrec_Unix || 153 Prec == k_PropVar_TimePrec_DOS) 154 return 0; 155 if (Prec == k_PropVar_TimePrec_HighPrec) 156 return 9; 157 if (Prec == k_PropVar_TimePrec_0) 158 return 7; 159 int digits = (int)Prec - (int)k_PropVar_TimePrec_Base; 160 if (digits < 0) 161 digits = 0; 162 return digits; 163 } 164 Write_To_FiTimeCArcTime165 void Write_To_FiTime(CFiTime &dest) const 166 { 167 #ifdef _WIN32 168 dest = FT; 169 #else 170 if (FILETIME_To_timespec(FT, dest)) 171 if ((Prec == k_PropVar_TimePrec_Base + 8 || 172 Prec == k_PropVar_TimePrec_Base + 9) 173 && Ns100 != 0) 174 { 175 dest.tv_nsec += Ns100; 176 } 177 #endif 178 } 179 180 // (Def) is not set Set_From_FILETIMECArcTime181 void Set_From_FILETIME(const FILETIME &ft) 182 { 183 FT = ft; 184 // Prec = k_PropVar_TimePrec_CompatNTFS; 185 Prec = k_PropVar_TimePrec_Base + 7; 186 Ns100 = 0; 187 } 188 189 // (Def) is not set 190 // it set full form precision: k_PropVar_TimePrec_Base + numDigits Set_From_FiTimeCArcTime191 void Set_From_FiTime(const CFiTime &ts) 192 { 193 #ifdef _WIN32 194 FT = ts; 195 Prec = k_PropVar_TimePrec_Base + 7; 196 // Prec = k_PropVar_TimePrec_Base; // for debug 197 // Prec = 0; // for debug 198 Ns100 = 0; 199 #else 200 unsigned ns100; 201 FiTime_To_FILETIME_ns100(ts, FT, ns100); 202 Ns100 = (Byte)ns100; 203 Prec = k_PropVar_TimePrec_Base + 9; 204 #endif 205 } 206 Set_From_PropCArcTime207 void Set_From_Prop(const PROPVARIANT &prop) 208 { 209 FT = prop.filetime; 210 unsigned prec = 0; 211 unsigned ns100 = 0; 212 const unsigned prec_Temp = prop.wReserved1; 213 if (prec_Temp != 0 214 && prec_Temp <= k_PropVar_TimePrec_1ns 215 && prop.wReserved3 == 0) 216 { 217 const unsigned ns100_Temp = prop.wReserved2; 218 if (ns100_Temp < 100) 219 { 220 ns100 = ns100_Temp; 221 prec = prec_Temp; 222 } 223 } 224 Prec = (UInt16)prec; 225 Ns100 = (Byte)ns100; 226 Def = true; 227 } 228 }; 229 230 231 struct CDirItem: public NWindows::NFile::NFind::CFileInfoBase 232 { 233 UString Name; 234 235 #ifndef UNDER_CE 236 CByteBuffer ReparseData; 237 238 #ifdef _WIN32 239 // UString ShortName; 240 CByteBuffer ReparseData2; // fixed (reduced) absolute links for WIM format AreReparseDataCDirItem241 bool AreReparseData() const { return ReparseData.Size() != 0 || ReparseData2.Size() != 0; } 242 #else AreReparseDataCDirItem243 bool AreReparseData() const { return ReparseData.Size() != 0; } 244 #endif // _WIN32 245 246 #endif // !UNDER_CE 247 Copy_From_FileInfoBaseCDirItem248 void Copy_From_FileInfoBase(const NWindows::NFile::NFind::CFileInfoBase &fi) 249 { 250 (NWindows::NFile::NFind::CFileInfoBase &)*this = fi; 251 } 252 253 int PhyParent; 254 int LogParent; 255 int SecureIndex; 256 257 #ifdef _WIN32 258 #else 259 int OwnerNameIndex; 260 int OwnerGroupIndex; 261 #endif 262 CDirItemCDirItem263 CDirItem(): 264 PhyParent(-1) 265 , LogParent(-1) 266 , SecureIndex(-1) 267 #ifdef _WIN32 268 #else 269 , OwnerNameIndex(-1) 270 , OwnerGroupIndex(-1) 271 #endif 272 { 273 } 274 275 CDirItemCDirItem276 CDirItem(const NWindows::NFile::NFind::CFileInfo &fi, 277 int phyParent, int logParent, int secureIndex): 278 CFileInfoBase(fi) 279 , Name(fs2us(fi.Name)) 280 #if defined(_WIN32) && !defined(UNDER_CE) 281 // , ShortName(fs2us(fi.ShortName)) 282 #endif 283 , PhyParent(phyParent) 284 , LogParent(logParent) 285 , SecureIndex(secureIndex) 286 #ifdef _WIN32 287 #else 288 , OwnerNameIndex(-1) 289 , OwnerGroupIndex(-1) 290 #endif 291 {} 292 }; 293 294 295 296 class CDirItems 297 { 298 UStringVector Prefixes; 299 CIntVector PhyParents; 300 CIntVector LogParents; 301 302 UString GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const; 303 304 HRESULT EnumerateDir(int phyParent, int logParent, const FString &phyPrefix); 305 306 public: 307 CObjectVector<CDirItem> Items; 308 309 bool SymLinks; 310 bool ScanAltStreams; 311 bool ExcludeDirItems; 312 bool ExcludeFileItems; 313 bool ShareForWrite; 314 315 /* it must be called after anotrher checks */ CanIncludeItem(bool isDir)316 bool CanIncludeItem(bool isDir) const 317 { 318 return isDir ? !ExcludeDirItems : !ExcludeFileItems; 319 } 320 321 322 CDirItemsStat Stat; 323 324 #if !defined(UNDER_CE) 325 HRESULT SetLinkInfo(CDirItem &dirItem, const NWindows::NFile::NFind::CFileInfo &fi, 326 const FString &phyPrefix); 327 #endif 328 329 #if defined(_WIN32) && !defined(UNDER_CE) 330 331 CUniqBlocks SecureBlocks; 332 CByteBuffer TempSecureBuf; 333 bool _saclEnabled; 334 bool ReadSecure; 335 336 HRESULT AddSecurityItem(const FString &path, int &secureIndex); 337 HRESULT FillFixedReparse(); 338 339 #endif 340 341 #ifndef _WIN32 342 343 C_UInt32_UString_Map OwnerNameMap; 344 C_UInt32_UString_Map OwnerGroupMap; 345 bool StoreOwnerName; 346 347 HRESULT FillDeviceSizes(); 348 349 #endif 350 351 IDirItemsCallback *Callback; 352 353 CDirItems(); 354 355 void AddDirFileInfo(int phyParent, int logParent, int secureIndex, 356 const NWindows::NFile::NFind::CFileInfo &fi); 357 358 HRESULT AddError(const FString &path, DWORD errorCode); 359 HRESULT AddError(const FString &path); 360 361 HRESULT ScanProgress(const FString &path); 362 363 // unsigned GetNumFolders() const { return Prefixes.Size(); } 364 FString GetPhyPath(unsigned index) const; 365 UString GetLogPath(unsigned index) const; 366 367 unsigned AddPrefix(int phyParent, int logParent, const UString &prefix); 368 void DeleteLastPrefix(); 369 370 // HRESULT EnumerateOneDir(const FString &phyPrefix, CObjectVector<NWindows::NFile::NFind::CDirEntry> &files); 371 HRESULT EnumerateOneDir(const FString &phyPrefix, CObjectVector<NWindows::NFile::NFind::CFileInfo> &files); 372 373 HRESULT EnumerateItems2( 374 const FString &phyPrefix, 375 const UString &logPrefix, 376 const FStringVector &filePaths, 377 FStringVector *requestedPaths); 378 379 void ReserveDown(); 380 }; 381 382 383 384 385 struct CArcItem 386 { 387 UInt64 Size; 388 UString Name; 389 CArcTime MTime; // it can be mtime of archive file, if MTime is not defined for item in archive 390 bool IsDir; 391 bool IsAltStream; 392 bool Size_Defined; 393 bool Censored; 394 UInt32 IndexInServer; 395 CArcItemCArcItem396 CArcItem(): 397 IsDir(false), 398 IsAltStream(false), 399 Size_Defined(false), 400 Censored(false) 401 {} 402 }; 403 404 #endif 405