| 281 | } |
| 282 | |
| 283 | UInt32 FileSystem::ListFiles(Exception& ex, const char* path, const ForEach& forEach, Mode mode) { |
| 284 | string directory(*path ? path : "."); |
| 285 | MakeFolder(directory); |
| 286 | UInt32 count(0); |
| 287 | string file; |
| 288 | |
| 289 | #if defined(_WIN32) |
| 290 | wchar_t wDirectory[_MAX_PATH]; |
| 291 | wDirectory[MultiByteToWideChar(CP_UTF8, 0, directory.data(), directory.size(), wDirectory, _MAX_PATH)] = '*'; |
| 292 | wDirectory[directory.size()+1] = 0; |
| 293 | |
| 294 | WIN32_FIND_DATAW fileData; |
| 295 | HANDLE fileHandle = FindFirstFileW(wDirectory, &fileData); |
| 296 | if (fileHandle == INVALID_HANDLE_VALUE) { |
| 297 | if (GetLastError() != ERROR_NO_MORE_FILES) |
| 298 | ex.set(Exception::FILE, "Cannot list files of directory ", directory); |
| 299 | return 0; |
| 300 | } |
| 301 | do { |
| 302 | if (wcscmp(fileData.cFileName, L".") != 0 && wcscmp(fileData.cFileName, L"..") != 0) { |
| 303 | ++count; |
| 304 | String::Format(file,directory, fileData.cFileName); |
| 305 | if (fileData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) { |
| 306 | file += '/'; |
| 307 | if (mode) |
| 308 | count += ListFiles(ex, file, forEach, Mode(mode+1)); |
| 309 | } |
| 310 | forEach(file,mode ? (UInt16(mode)-1) : 0); |
| 311 | } |
| 312 | } while (FindNextFileW(fileHandle, &fileData) != 0); |
| 313 | FindClose(fileHandle); |
| 314 | #else |
| 315 | DIR* pDirectory = opendir(directory.c_str()); |
| 316 | if (!pDirectory) { |
| 317 | ex.set(Exception::FILE, "Cannot list files of directory ",directory); |
| 318 | return 0; |
| 319 | } |
| 320 | struct dirent* pEntry(NULL); |
| 321 | while((pEntry = readdir(pDirectory))) { |
| 322 | if (strcmp(pEntry->d_name, ".")!=0 && strcmp(pEntry->d_name, "..")!=0) { |
| 323 | ++count; |
| 324 | String::Format(file, directory, pEntry->d_name); |
| 325 | // Cross-platform solution when DT_UNKNOWN or symbolic link |
| 326 | bool isFolder(false); |
| 327 | if(pEntry->d_type==DT_DIR) { |
| 328 | isFolder = true; |
| 329 | } else if(pEntry->d_type==DT_UNKNOWN || pEntry->d_type==DT_LNK) { |
| 330 | Status status; |
| 331 | Stat(file.data(), file.size(), status); |
| 332 | if ((status.st_mode&S_IFMT) == S_IFDIR) |
| 333 | isFolder = true; |
| 334 | } |
| 335 | if(isFolder) { |
| 336 | file += '/'; |
| 337 | if (mode) |
| 338 | count += ListFiles(ex, file, forEach, Mode(mode+1)); |
| 339 | } |
| 340 | forEach(file,mode ? (UInt16(mode)-1) : 0); |