returns true if successful, false otherwise
| 1097 | |
| 1098 | // returns true if successful, false otherwise |
| 1099 | bool create_directory_with_parents(const std::string & path) { |
| 1100 | #ifdef _WIN32 |
| 1101 | std::wstring_convert<std::codecvt_utf8<wchar_t>> converter; |
| 1102 | std::wstring wpath = converter.from_bytes(path); |
| 1103 | |
| 1104 | // if the path already exists, check whether it's a directory |
| 1105 | const DWORD attributes = GetFileAttributesW(wpath.c_str()); |
| 1106 | if ((attributes != INVALID_FILE_ATTRIBUTES) && (attributes & FILE_ATTRIBUTE_DIRECTORY)) { |
| 1107 | return true; |
| 1108 | } |
| 1109 | |
| 1110 | size_t pos_slash = 0; |
| 1111 | |
| 1112 | // process path from front to back, procedurally creating directories |
| 1113 | while ((pos_slash = path.find('\\', pos_slash)) != std::string::npos) { |
| 1114 | const std::wstring subpath = wpath.substr(0, pos_slash); |
| 1115 | const wchar_t * test = subpath.c_str(); |
| 1116 | |
| 1117 | const bool success = CreateDirectoryW(test, NULL); |
| 1118 | if (!success) { |
| 1119 | const DWORD error = GetLastError(); |
| 1120 | |
| 1121 | // if the path already exists, ensure that it's a directory |
| 1122 | if (error == ERROR_ALREADY_EXISTS) { |
| 1123 | const DWORD attributes = GetFileAttributesW(subpath.c_str()); |
| 1124 | if (attributes == INVALID_FILE_ATTRIBUTES || !(attributes & FILE_ATTRIBUTE_DIRECTORY)) { |
| 1125 | return false; |
| 1126 | } |
| 1127 | } else { |
| 1128 | return false; |
| 1129 | } |
| 1130 | } |
| 1131 | |
| 1132 | pos_slash += 1; |
| 1133 | } |
| 1134 | |
| 1135 | return true; |
| 1136 | #else |
| 1137 | // if the path already exists, check whether it's a directory |
| 1138 | struct stat info; |
| 1139 | if (stat(path.c_str(), &info) == 0) { |
| 1140 | return S_ISDIR(info.st_mode); |
| 1141 | } |
| 1142 | |
| 1143 | size_t pos_slash = 1; // skip leading slashes for directory creation |
| 1144 | |
| 1145 | // process path from front to back, procedurally creating directories |
| 1146 | while ((pos_slash = path.find('/', pos_slash)) != std::string::npos) { |
| 1147 | const std::string subpath = path.substr(0, pos_slash); |
| 1148 | struct stat info; |
| 1149 | |
| 1150 | // if the path already exists, ensure that it's a directory |
| 1151 | if (stat(subpath.c_str(), &info) == 0) { |
| 1152 | if (!S_ISDIR(info.st_mode)) { |
| 1153 | return false; |
| 1154 | } |
| 1155 | } else { |
| 1156 | // create parent directories |
no test coverage detected