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 263 // bool Attrib_IsDefined; 264 CDirItemCDirItem265 CDirItem(): 266 PhyParent(-1) 267 , LogParent(-1) 268 , SecureIndex(-1) 269 #ifdef _WIN32 270 #else 271 , OwnerNameIndex(-1) 272 , OwnerGroupIndex(-1) 273 #endif 274 // , Attrib_IsDefined(true) 275 { 276 } 277 278 CDirItemCDirItem279 CDirItem(const NWindows::NFile::NFind::CFileInfo &fi, 280 int phyParent, int logParent, int secureIndex): 281 CFileInfoBase(fi) 282 , Name(fs2us(fi.Name)) 283 #if defined(_WIN32) && !defined(UNDER_CE) 284 // , ShortName(fs2us(fi.ShortName)) 285 #endif 286 , PhyParent(phyParent) 287 , LogParent(logParent) 288 , SecureIndex(secureIndex) 289 #ifdef _WIN32 290 #else 291 , OwnerNameIndex(-1) 292 , OwnerGroupIndex(-1) 293 #endif 294 {} 295 }; 296 297 298 299 class CDirItems 300 { 301 UStringVector Prefixes; 302 CIntVector PhyParents; 303 CIntVector LogParents; 304 305 UString GetPrefixesPath(const CIntVector &parents, int index, const UString &name) const; 306 307 HRESULT EnumerateDir(int phyParent, int logParent, const FString &phyPrefix); 308 309 public: 310 CObjectVector<CDirItem> Items; 311 312 bool SymLinks; 313 bool ScanAltStreams; 314 bool ExcludeDirItems; 315 bool ExcludeFileItems; 316 bool ShareForWrite; 317 318 /* it must be called after anotrher checks */ CanIncludeItem(bool isDir)319 bool CanIncludeItem(bool isDir) const 320 { 321 return isDir ? !ExcludeDirItems : !ExcludeFileItems; 322 } 323 324 325 CDirItemsStat Stat; 326 327 #if !defined(UNDER_CE) 328 HRESULT SetLinkInfo(CDirItem &dirItem, const NWindows::NFile::NFind::CFileInfo &fi, 329 const FString &phyPrefix); 330 #endif 331 332 #if defined(_WIN32) && !defined(UNDER_CE) 333 334 CUniqBlocks SecureBlocks; 335 CByteBuffer TempSecureBuf; 336 bool _saclEnabled; 337 bool ReadSecure; 338 339 HRESULT AddSecurityItem(const FString &path, int &secureIndex); 340 HRESULT FillFixedReparse(); 341 342 #endif 343 344 #ifndef _WIN32 345 346 C_UInt32_UString_Map OwnerNameMap; 347 C_UInt32_UString_Map OwnerGroupMap; 348 bool StoreOwnerName; 349 350 HRESULT FillDeviceSizes(); 351 352 #endif 353 354 IDirItemsCallback *Callback; 355 356 CDirItems(); 357 358 void AddDirFileInfo(int phyParent, int logParent, int secureIndex, 359 const NWindows::NFile::NFind::CFileInfo &fi); 360 361 HRESULT AddError(const FString &path, DWORD errorCode); 362 HRESULT AddError(const FString &path); 363 364 HRESULT ScanProgress(const FString &path); 365 366 // unsigned GetNumFolders() const { return Prefixes.Size(); } 367 FString GetPhyPath(unsigned index) const; 368 UString GetLogPath(unsigned index) const; 369 370 unsigned AddPrefix(int phyParent, int logParent, const UString &prefix); 371 void DeleteLastPrefix(); 372 373 // HRESULT EnumerateOneDir(const FString &phyPrefix, CObjectVector<NWindows::NFile::NFind::CDirEntry> &files); 374 HRESULT EnumerateOneDir(const FString &phyPrefix, CObjectVector<NWindows::NFile::NFind::CFileInfo> &files); 375 376 HRESULT EnumerateItems2( 377 const FString &phyPrefix, 378 const UString &logPrefix, 379 const FStringVector &filePaths, 380 FStringVector *requestedPaths); 381 382 void ReserveDown(); 383 }; 384 385 386 387 388 struct CArcItem 389 { 390 UInt64 Size; 391 UString Name; 392 CArcTime MTime; // it can be mtime of archive file, if MTime is not defined for item in archive 393 bool IsDir; 394 bool IsAltStream; 395 bool Size_Defined; 396 bool Censored; 397 UInt32 IndexInServer; 398 CArcItemCArcItem399 CArcItem(): 400 IsDir(false), 401 IsAltStream(false), 402 Size_Defined(false), 403 Censored(false) 404 {} 405 }; 406 407 #endif 408