| 150 | } |
| 151 | |
| 152 | static bool copyRecursive(const std::string& src, const std::string& dst) { |
| 153 | if (file::isDirectory(src)) { |
| 154 | if (!file::findOrCreateDirectory(dst, 0755)) { |
| 155 | return false; |
| 156 | } |
| 157 | |
| 158 | // Process one entry at a time: release the device lock between iterations |
| 159 | // so other SPI bus users aren't starved, and stop immediately on failure. |
| 160 | auto lock = file::getLock(src); |
| 161 | lock->lock(); |
| 162 | DIR* dir = opendir(src.c_str()); |
| 163 | if (!dir) { |
| 164 | lock->unlock(); |
| 165 | file::deleteRecursively(dst); |
| 166 | return false; |
| 167 | } |
| 168 | |
| 169 | bool success = true; |
| 170 | while (success) { |
| 171 | struct dirent* entry = readdir(dir); |
| 172 | if (!entry) break; |
| 173 | if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) continue; |
| 174 | |
| 175 | std::string name = entry->d_name; // copy before releasing lock |
| 176 | lock->unlock(); |
| 177 | |
| 178 | success = copyRecursive(file::getChildPath(src, name), file::getChildPath(dst, name)); |
| 179 | |
| 180 | lock->lock(); |
| 181 | } |
| 182 | closedir(dir); |
| 183 | lock->unlock(); |
| 184 | |
| 185 | if (!success) { |
| 186 | file::deleteRecursively(dst); |
| 187 | } |
| 188 | return success; |
| 189 | } else { |
| 190 | return copyFileContents(src, dst); |
| 191 | } |
| 192 | } |
| 193 | |
| 194 | // endregion |
| 195 |
no test coverage detected