| 185 | } |
| 186 | |
| 187 | Result io::copyTree(FS_Archive srcArch, FS_Archive dstArch, const std::u16string& srcRoot, const std::u16string& dstRoot, |
| 188 | const std::vector<TreeEntry>& entries, ProgressSink& sink) |
| 189 | { |
| 190 | // One scratch buffer for every file in the tree instead of a per-file new/delete. |
| 191 | auto buf = std::make_unique<u8[]>(BUFFER_SIZE); |
| 192 | Result res = 0; |
| 193 | |
| 194 | for (const auto& entry : entries) { |
| 195 | if (sink.cancelled()) { |
| 196 | break; |
| 197 | } |
| 198 | std::u16string dst = dstRoot + entry.rel; |
| 199 | if (entry.folder) { |
| 200 | res = io::createDirectory(dstArch, dst); |
| 201 | // 0xC82044B9 == directory already exists; treat as success. |
| 202 | if (R_FAILED(res) && (u32)res != 0xC82044B9) { |
| 203 | return res; |
| 204 | } |
| 205 | res = 0; |
| 206 | } |
| 207 | else { |
| 208 | res = io::copyFile(srcArch, dstArch, srcRoot + entry.rel, dst, sink, buf.get()); |
| 209 | if (R_FAILED(res)) { |
| 210 | return res; |
| 211 | } |
| 212 | } |
| 213 | } |
| 214 | |
| 215 | return res; |
| 216 | } |
| 217 | |
| 218 | Result io::createDirectory(FS_Archive archive, const std::u16string& path) |
| 219 | { |