| 2388 | namespace platform { |
| 2389 | |
| 2390 | bool createDirectory(std::string const& directory) { |
| 2391 | INJECT_FAULT(platform_error, "createDirectory"); // create dir failed |
| 2392 | |
| 2393 | #ifdef _WIN32 |
| 2394 | if (CreateDirectory(directory.c_str(), nullptr)) { |
| 2395 | createdDirectory(); |
| 2396 | return true; |
| 2397 | } |
| 2398 | if (GetLastError() == ERROR_ALREADY_EXISTS) |
| 2399 | return false; |
| 2400 | if (GetLastError() == ERROR_PATH_NOT_FOUND) { |
| 2401 | size_t delim = directory.find_last_of("/\\"); |
| 2402 | if (delim != std::string::npos) { |
| 2403 | createDirectory(directory.substr(0, delim)); |
| 2404 | return createDirectory(directory); |
| 2405 | } |
| 2406 | } |
| 2407 | Error e = systemErrorCodeToError(); |
| 2408 | TraceEvent(SevError, "CreateDirectory").error(e).detail("Directory", directory).GetLastError(); |
| 2409 | throw e; |
| 2410 | #elif (defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__)) |
| 2411 | size_t sep = 0; |
| 2412 | do { |
| 2413 | sep = directory.find_first_of('/', sep + 1); |
| 2414 | if (mkdir(directory.substr(0, sep).c_str(), 0755) != 0) { |
| 2415 | if (errno == EEXIST) |
| 2416 | continue; |
| 2417 | auto mkdirErrno = errno; |
| 2418 | |
| 2419 | // check if directory already exists |
| 2420 | // necessary due to old kernel bugs |
| 2421 | struct stat s; |
| 2422 | const char* dirname = directory.c_str(); |
| 2423 | if (stat(dirname, &s) != -1 && S_ISDIR(s.st_mode)) { |
| 2424 | TraceEvent("DirectoryAlreadyExists").detail("Directory", dirname).detail("IgnoredError", mkdirErrno); |
| 2425 | continue; |
| 2426 | } |
| 2427 | |
| 2428 | Error e; |
| 2429 | if (mkdirErrno == EACCES) { |
| 2430 | e = file_not_writable(); |
| 2431 | } else { |
| 2432 | e = systemErrorCodeToError(); |
| 2433 | } |
| 2434 | |
| 2435 | TraceEvent(SevError, "CreateDirectory") |
| 2436 | .error(e) |
| 2437 | .detail("Directory", directory) |
| 2438 | .detailf("UnixErrorCode", "%x", errno) |
| 2439 | .detail("UnixError", strerror(mkdirErrno)); |
| 2440 | throw e; |
| 2441 | } |
| 2442 | createdDirectory(); |
| 2443 | } while (sep != std::string::npos && sep != directory.length() - 1); |
| 2444 | return true; |
| 2445 | #else |
| 2446 | #error Port me! |
| 2447 | #endif |