annotate src/win32/7zip/7z/CPP/Windows/FileFind.cpp @ 1:f9f4f1b99eed

importing src directory
author Robert McIntyre <rlm@mit.edu>
date Sat, 03 Mar 2012 10:31:27 -0600
parents
children
rev   line source
rlm@1 1 // Windows/FileFind.cpp
rlm@1 2
rlm@1 3 #include "StdAfx.h"
rlm@1 4
rlm@1 5 #include "FileFind.h"
rlm@1 6 #ifndef _UNICODE
rlm@1 7 #include "../Common/StringConvert.h"
rlm@1 8 #endif
rlm@1 9
rlm@1 10 #ifndef _UNICODE
rlm@1 11 extern bool g_IsNT;
rlm@1 12 #endif
rlm@1 13
rlm@1 14 namespace NWindows {
rlm@1 15 namespace NFile {
rlm@1 16
rlm@1 17 #if defined(WIN_LONG_PATH) && defined(_UNICODE)
rlm@1 18 #define WIN_LONG_PATH2
rlm@1 19 #endif
rlm@1 20
rlm@1 21 bool GetLongPath(LPCWSTR fileName, UString &res);
rlm@1 22
rlm@1 23 namespace NFind {
rlm@1 24
rlm@1 25 static const TCHAR kDot = TEXT('.');
rlm@1 26
rlm@1 27 bool CFileInfo::IsDots() const
rlm@1 28 {
rlm@1 29 if (!IsDir() || Name.IsEmpty())
rlm@1 30 return false;
rlm@1 31 if (Name[0] != kDot)
rlm@1 32 return false;
rlm@1 33 return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2);
rlm@1 34 }
rlm@1 35
rlm@1 36 #ifndef _UNICODE
rlm@1 37 bool CFileInfoW::IsDots() const
rlm@1 38 {
rlm@1 39 if (!IsDir() || Name.IsEmpty())
rlm@1 40 return false;
rlm@1 41 if (Name[0] != kDot)
rlm@1 42 return false;
rlm@1 43 return Name.Length() == 1 || (Name[1] == kDot && Name.Length() == 2);
rlm@1 44 }
rlm@1 45 #endif
rlm@1 46
rlm@1 47 static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfo &fi)
rlm@1 48 {
rlm@1 49 fi.Attrib = fd.dwFileAttributes;
rlm@1 50 fi.CTime = fd.ftCreationTime;
rlm@1 51 fi.ATime = fd.ftLastAccessTime;
rlm@1 52 fi.MTime = fd.ftLastWriteTime;
rlm@1 53 fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow;
rlm@1 54 fi.Name = fd.cFileName;
rlm@1 55 #ifndef _WIN32_WCE
rlm@1 56 fi.ReparseTag = fd.dwReserved0;
rlm@1 57 #else
rlm@1 58 fi.ObjectID = fd.dwOID;
rlm@1 59 #endif
rlm@1 60 }
rlm@1 61
rlm@1 62 #ifndef _UNICODE
rlm@1 63
rlm@1 64 static inline UINT GetCurrentCodePage() { return ::AreFileApisANSI() ? CP_ACP : CP_OEMCP; }
rlm@1 65
rlm@1 66 static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATAW &fd, CFileInfoW &fi)
rlm@1 67 {
rlm@1 68 fi.Attrib = fd.dwFileAttributes;
rlm@1 69 fi.CTime = fd.ftCreationTime;
rlm@1 70 fi.ATime = fd.ftLastAccessTime;
rlm@1 71 fi.MTime = fd.ftLastWriteTime;
rlm@1 72 fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow;
rlm@1 73 fi.Name = fd.cFileName;
rlm@1 74 #ifndef _WIN32_WCE
rlm@1 75 fi.ReparseTag = fd.dwReserved0;
rlm@1 76 #else
rlm@1 77 fi.ObjectID = fd.dwOID;
rlm@1 78 #endif
rlm@1 79 }
rlm@1 80
rlm@1 81 static void ConvertWIN32_FIND_DATA_To_FileInfo(const WIN32_FIND_DATA &fd, CFileInfoW &fi)
rlm@1 82 {
rlm@1 83 fi.Attrib = fd.dwFileAttributes;
rlm@1 84 fi.CTime = fd.ftCreationTime;
rlm@1 85 fi.ATime = fd.ftLastAccessTime;
rlm@1 86 fi.MTime = fd.ftLastWriteTime;
rlm@1 87 fi.Size = (((UInt64)fd.nFileSizeHigh) << 32) + fd.nFileSizeLow;
rlm@1 88 fi.Name = GetUnicodeString(fd.cFileName, GetCurrentCodePage());
rlm@1 89 #ifndef _WIN32_WCE
rlm@1 90 fi.ReparseTag = fd.dwReserved0;
rlm@1 91 #else
rlm@1 92 fi.ObjectID = fd.dwOID;
rlm@1 93 #endif
rlm@1 94 }
rlm@1 95 #endif
rlm@1 96
rlm@1 97 ////////////////////////////////
rlm@1 98 // CFindFile
rlm@1 99
rlm@1 100 bool CFindFile::Close()
rlm@1 101 {
rlm@1 102 if (_handle == INVALID_HANDLE_VALUE)
rlm@1 103 return true;
rlm@1 104 if (!::FindClose(_handle))
rlm@1 105 return false;
rlm@1 106 _handle = INVALID_HANDLE_VALUE;
rlm@1 107 return true;
rlm@1 108 }
rlm@1 109
rlm@1 110
rlm@1 111 bool CFindFile::FindFirst(LPCTSTR wildcard, CFileInfo &fileInfo)
rlm@1 112 {
rlm@1 113 if (!Close())
rlm@1 114 return false;
rlm@1 115 WIN32_FIND_DATA fd;
rlm@1 116 _handle = ::FindFirstFile(wildcard, &fd);
rlm@1 117 #ifdef WIN_LONG_PATH2
rlm@1 118 if (_handle == INVALID_HANDLE_VALUE)
rlm@1 119 {
rlm@1 120 UString longPath;
rlm@1 121 if (GetLongPath(wildcard, longPath))
rlm@1 122 _handle = ::FindFirstFileW(longPath, &fd);
rlm@1 123 }
rlm@1 124 #endif
rlm@1 125 if (_handle == INVALID_HANDLE_VALUE)
rlm@1 126 return false;
rlm@1 127 ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo);
rlm@1 128 return true;
rlm@1 129 }
rlm@1 130
rlm@1 131 #ifndef _UNICODE
rlm@1 132 bool CFindFile::FindFirst(LPCWSTR wildcard, CFileInfoW &fileInfo)
rlm@1 133 {
rlm@1 134 if (!Close())
rlm@1 135 return false;
rlm@1 136 if (g_IsNT)
rlm@1 137 {
rlm@1 138 WIN32_FIND_DATAW fd;
rlm@1 139 _handle = ::FindFirstFileW(wildcard, &fd);
rlm@1 140 #ifdef WIN_LONG_PATH
rlm@1 141 if (_handle == INVALID_HANDLE_VALUE)
rlm@1 142 {
rlm@1 143 UString longPath;
rlm@1 144 if (GetLongPath(wildcard, longPath))
rlm@1 145 _handle = ::FindFirstFileW(longPath, &fd);
rlm@1 146 }
rlm@1 147 #endif
rlm@1 148 if (_handle != INVALID_HANDLE_VALUE)
rlm@1 149 ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo);
rlm@1 150 }
rlm@1 151 else
rlm@1 152 {
rlm@1 153 WIN32_FIND_DATAA fd;
rlm@1 154 _handle = ::FindFirstFileA(UnicodeStringToMultiByte(wildcard,
rlm@1 155 GetCurrentCodePage()), &fd);
rlm@1 156 if (_handle != INVALID_HANDLE_VALUE)
rlm@1 157 ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo);
rlm@1 158 }
rlm@1 159 return (_handle != INVALID_HANDLE_VALUE);
rlm@1 160 }
rlm@1 161 #endif
rlm@1 162
rlm@1 163 bool CFindFile::FindNext(CFileInfo &fileInfo)
rlm@1 164 {
rlm@1 165 WIN32_FIND_DATA fd;
rlm@1 166 bool result = BOOLToBool(::FindNextFile(_handle, &fd));
rlm@1 167 if (result)
rlm@1 168 ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo);
rlm@1 169 return result;
rlm@1 170 }
rlm@1 171
rlm@1 172 #ifndef _UNICODE
rlm@1 173 bool CFindFile::FindNext(CFileInfoW &fileInfo)
rlm@1 174 {
rlm@1 175 if (g_IsNT)
rlm@1 176 {
rlm@1 177 WIN32_FIND_DATAW fd;
rlm@1 178 if (!::FindNextFileW(_handle, &fd))
rlm@1 179 return false;
rlm@1 180 ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo);
rlm@1 181 }
rlm@1 182 else
rlm@1 183 {
rlm@1 184 WIN32_FIND_DATAA fd;
rlm@1 185 if (!::FindNextFileA(_handle, &fd))
rlm@1 186 return false;
rlm@1 187 ConvertWIN32_FIND_DATA_To_FileInfo(fd, fileInfo);
rlm@1 188 }
rlm@1 189 return true;
rlm@1 190 }
rlm@1 191 #endif
rlm@1 192
rlm@1 193 bool FindFile(LPCTSTR wildcard, CFileInfo &fileInfo)
rlm@1 194 {
rlm@1 195 CFindFile finder;
rlm@1 196 return finder.FindFirst(wildcard, fileInfo);
rlm@1 197 }
rlm@1 198
rlm@1 199 #ifndef _UNICODE
rlm@1 200 bool FindFile(LPCWSTR wildcard, CFileInfoW &fileInfo)
rlm@1 201 {
rlm@1 202 CFindFile finder;
rlm@1 203 return finder.FindFirst(wildcard, fileInfo);
rlm@1 204 }
rlm@1 205 #endif
rlm@1 206
rlm@1 207 bool DoesFileExist(LPCTSTR name)
rlm@1 208 {
rlm@1 209 CFileInfo fileInfo;
rlm@1 210 return FindFile(name, fileInfo);
rlm@1 211 }
rlm@1 212
rlm@1 213 #ifndef _UNICODE
rlm@1 214 bool DoesFileExist(LPCWSTR name)
rlm@1 215 {
rlm@1 216 CFileInfoW fileInfo;
rlm@1 217 return FindFile(name, fileInfo);
rlm@1 218 }
rlm@1 219 #endif
rlm@1 220
rlm@1 221 /////////////////////////////////////
rlm@1 222 // CEnumerator
rlm@1 223
rlm@1 224 bool CEnumerator::NextAny(CFileInfo &fileInfo)
rlm@1 225 {
rlm@1 226 if (_findFile.IsHandleAllocated())
rlm@1 227 return _findFile.FindNext(fileInfo);
rlm@1 228 else
rlm@1 229 return _findFile.FindFirst(_wildcard, fileInfo);
rlm@1 230 }
rlm@1 231
rlm@1 232 bool CEnumerator::Next(CFileInfo &fileInfo)
rlm@1 233 {
rlm@1 234 for (;;)
rlm@1 235 {
rlm@1 236 if (!NextAny(fileInfo))
rlm@1 237 return false;
rlm@1 238 if (!fileInfo.IsDots())
rlm@1 239 return true;
rlm@1 240 }
rlm@1 241 }
rlm@1 242
rlm@1 243 bool CEnumerator::Next(CFileInfo &fileInfo, bool &found)
rlm@1 244 {
rlm@1 245 if (Next(fileInfo))
rlm@1 246 {
rlm@1 247 found = true;
rlm@1 248 return true;
rlm@1 249 }
rlm@1 250 found = false;
rlm@1 251 return (::GetLastError() == ERROR_NO_MORE_FILES);
rlm@1 252 }
rlm@1 253
rlm@1 254 #ifndef _UNICODE
rlm@1 255 bool CEnumeratorW::NextAny(CFileInfoW &fileInfo)
rlm@1 256 {
rlm@1 257 if (_findFile.IsHandleAllocated())
rlm@1 258 return _findFile.FindNext(fileInfo);
rlm@1 259 else
rlm@1 260 return _findFile.FindFirst(_wildcard, fileInfo);
rlm@1 261 }
rlm@1 262
rlm@1 263 bool CEnumeratorW::Next(CFileInfoW &fileInfo)
rlm@1 264 {
rlm@1 265 for (;;)
rlm@1 266 {
rlm@1 267 if (!NextAny(fileInfo))
rlm@1 268 return false;
rlm@1 269 if (!fileInfo.IsDots())
rlm@1 270 return true;
rlm@1 271 }
rlm@1 272 }
rlm@1 273
rlm@1 274 bool CEnumeratorW::Next(CFileInfoW &fileInfo, bool &found)
rlm@1 275 {
rlm@1 276 if (Next(fileInfo))
rlm@1 277 {
rlm@1 278 found = true;
rlm@1 279 return true;
rlm@1 280 }
rlm@1 281 found = false;
rlm@1 282 return (::GetLastError() == ERROR_NO_MORE_FILES);
rlm@1 283 }
rlm@1 284
rlm@1 285 #endif
rlm@1 286
rlm@1 287 ////////////////////////////////
rlm@1 288 // CFindChangeNotification
rlm@1 289 // FindFirstChangeNotification can return 0. MSDN doesn't tell about it.
rlm@1 290
rlm@1 291 bool CFindChangeNotification::Close()
rlm@1 292 {
rlm@1 293 if (!IsHandleAllocated())
rlm@1 294 return true;
rlm@1 295 if (!::FindCloseChangeNotification(_handle))
rlm@1 296 return false;
rlm@1 297 _handle = INVALID_HANDLE_VALUE;
rlm@1 298 return true;
rlm@1 299 }
rlm@1 300
rlm@1 301 HANDLE CFindChangeNotification::FindFirst(LPCTSTR pathName, bool watchSubtree, DWORD notifyFilter)
rlm@1 302 {
rlm@1 303 _handle = ::FindFirstChangeNotification(pathName, BoolToBOOL(watchSubtree), notifyFilter);
rlm@1 304 #ifdef WIN_LONG_PATH2
rlm@1 305 if (!IsHandleAllocated())
rlm@1 306 {
rlm@1 307 UString longPath;
rlm@1 308 if (GetLongPath(pathName, longPath))
rlm@1 309 _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter);
rlm@1 310 }
rlm@1 311 #endif
rlm@1 312 return _handle;
rlm@1 313 }
rlm@1 314
rlm@1 315 #ifndef _UNICODE
rlm@1 316 HANDLE CFindChangeNotification::FindFirst(LPCWSTR pathName, bool watchSubtree, DWORD notifyFilter)
rlm@1 317 {
rlm@1 318 if (!g_IsNT)
rlm@1 319 return FindFirst(UnicodeStringToMultiByte(pathName, GetCurrentCodePage()), watchSubtree, notifyFilter);
rlm@1 320 _handle = ::FindFirstChangeNotificationW(pathName, BoolToBOOL(watchSubtree), notifyFilter);
rlm@1 321 #ifdef WIN_LONG_PATH
rlm@1 322 if (!IsHandleAllocated())
rlm@1 323 {
rlm@1 324 UString longPath;
rlm@1 325 if (GetLongPath(pathName, longPath))
rlm@1 326 _handle = ::FindFirstChangeNotificationW(longPath, BoolToBOOL(watchSubtree), notifyFilter);
rlm@1 327 }
rlm@1 328 #endif
rlm@1 329 return _handle;
rlm@1 330 }
rlm@1 331 #endif
rlm@1 332
rlm@1 333 #ifndef _WIN32_WCE
rlm@1 334 bool MyGetLogicalDriveStrings(CSysStringVector &driveStrings)
rlm@1 335 {
rlm@1 336 driveStrings.Clear();
rlm@1 337 UINT32 size = GetLogicalDriveStrings(0, NULL);
rlm@1 338 if (size == 0)
rlm@1 339 return false;
rlm@1 340 CSysString buffer;
rlm@1 341 UINT32 newSize = GetLogicalDriveStrings(size, buffer.GetBuffer(size));
rlm@1 342 if (newSize == 0)
rlm@1 343 return false;
rlm@1 344 if (newSize > size)
rlm@1 345 return false;
rlm@1 346 CSysString string;
rlm@1 347 for (UINT32 i = 0; i < newSize; i++)
rlm@1 348 {
rlm@1 349 TCHAR c = buffer[i];
rlm@1 350 if (c == TEXT('\0'))
rlm@1 351 {
rlm@1 352 driveStrings.Add(string);
rlm@1 353 string.Empty();
rlm@1 354 }
rlm@1 355 else
rlm@1 356 string += c;
rlm@1 357 }
rlm@1 358 if (!string.IsEmpty())
rlm@1 359 return false;
rlm@1 360 return true;
rlm@1 361 }
rlm@1 362
rlm@1 363 #ifndef _UNICODE
rlm@1 364 bool MyGetLogicalDriveStrings(UStringVector &driveStrings)
rlm@1 365 {
rlm@1 366 driveStrings.Clear();
rlm@1 367 if (g_IsNT)
rlm@1 368 {
rlm@1 369 UINT32 size = GetLogicalDriveStringsW(0, NULL);
rlm@1 370 if (size == 0)
rlm@1 371 return false;
rlm@1 372 UString buffer;
rlm@1 373 UINT32 newSize = GetLogicalDriveStringsW(size, buffer.GetBuffer(size));
rlm@1 374 if (newSize == 0)
rlm@1 375 return false;
rlm@1 376 if (newSize > size)
rlm@1 377 return false;
rlm@1 378 UString string;
rlm@1 379 for (UINT32 i = 0; i < newSize; i++)
rlm@1 380 {
rlm@1 381 WCHAR c = buffer[i];
rlm@1 382 if (c == L'\0')
rlm@1 383 {
rlm@1 384 driveStrings.Add(string);
rlm@1 385 string.Empty();
rlm@1 386 }
rlm@1 387 else
rlm@1 388 string += c;
rlm@1 389 }
rlm@1 390 return string.IsEmpty();
rlm@1 391 }
rlm@1 392 CSysStringVector driveStringsA;
rlm@1 393 bool res = MyGetLogicalDriveStrings(driveStringsA);
rlm@1 394 for (int i = 0; i < driveStringsA.Size(); i++)
rlm@1 395 driveStrings.Add(GetUnicodeString(driveStringsA[i]));
rlm@1 396 return res;
rlm@1 397 }
rlm@1 398 #endif
rlm@1 399
rlm@1 400 #endif
rlm@1 401
rlm@1 402 }}}