MCPcopy Create free account
hub / github.com/BernardoGiordano/Checkpoint / copyFile

Method copyFile

3ds/source/io.cpp:186–259  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

184}
185
186Result io::copyFile(
187 FS_Archive srcArch, FS_Archive dstArch, const std::u16string& srcPath, const std::u16string& dstPath, ProgressSink& sink, u8* buffer)
188{
189 u32 size = 0;
190 FSStream input(srcArch, srcPath, FS_OPEN_READ);
191 if (input.good()) {
192 size = input.size() > BUFFER_SIZE ? BUFFER_SIZE : input.size();
193 }
194 else {
195 Logging::error("Failed to open source file {} during copy with result {}.", StringUtils::UTF16toUTF8(srcPath), input.result());
196 return input.result();
197 }
198
199 FSStream output(dstArch, dstPath, FS_OPEN_WRITE, input.size());
200 if (!output.good()) {
201 Logging::error("Failed to open destination file {} during copy with result {}.", StringUtils::UTF16toUTF8(dstPath), output.result());
202 input.close();
203 return output.result();
204 }
205
206 size_t slashpos = srcPath.rfind(StringUtils::UTF8toUTF16("/"));
207 sink.startFile(srcPath.substr(slashpos + 1, srcPath.length() - slashpos - 1), input.size());
208
209 Result res = 0;
210 u32 offset = 0;
211 u32 chunk = size; // shrinks toward the readable-data boundary on RES_FS_PAST_DATA
212 do {
213 if (sink.cancelled()) {
214 break;
215 }
216 u32 rd = input.read(buffer, chunk);
217 if (R_FAILED(input.result())) {
218 // Sparse extdata: this offset+chunk runs past the file's real data. Halve
219 // the request to recover any readable prefix at this offset; once even a
220 // single byte can't be read here, we've hit the true end of data — stop
221 // this file cleanly and keep the backup going.
222 if ((u32)input.result() == RES_FS_PAST_DATA) {
223 if (chunk > 1) {
224 chunk /= 2;
225 continue;
226 }
227 Logging::info("Reached end of readable data for {} at offset {} (sparse extdata); backing up {} bytes.",
228 StringUtils::UTF16toUTF8(srcPath), offset, offset);
229 break;
230 }
231 res = input.result();
232 Logging::error("Read failure during copy of {} with result 0x{:08X}.", StringUtils::UTF16toUTF8(srcPath), (u32)res);
233 break;
234 }
235 if (rd == 0) {
236 break;
237 }
238 u32 wt = output.write(buffer, rd);
239 if (R_FAILED(output.result())) {
240 res = output.result();
241 Logging::error("Write failure during copy of {} with result 0x{:08X}.", StringUtils::UTF16toUTF8(dstPath), (u32)res);
242 break;
243 }

Callers

nothing calls this directly

Calls 13

resultMethod · 0.80
errorFunction · 0.50
infoFunction · 0.50
goodMethod · 0.45
sizeMethod · 0.45
closeMethod · 0.45
startFileMethod · 0.45
cancelledMethod · 0.45
readMethod · 0.45
writeMethod · 0.45
advanceBytesMethod · 0.45
eofMethod · 0.45

Tested by

no test coverage detected