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

Method copyFile

switch/source/io.cpp:246–341  ·  view source on GitHub ↗

Source from the content-addressed store, hash-verified

244}
245
246Result io::copyFile(const std::string& srcPath, const std::string& dstPath, ProgressSink& sink, u64 commitWriteLimit)
247{
248 FILE* src = fopen(srcPath.c_str(), "rb");
249 if (src == NULL) {
250 Logging::error("Failed to open source file {} during copy with errno {}.", srcPath, errno);
251 return RES_COPY_FAILED;
252 }
253 FILE* dst = fopen(dstPath.c_str(), "wb");
254 if (dst == NULL) {
255 Logging::error("Failed to open destination file {} during copy with errno {}.", dstPath, errno);
256 fclose(src);
257 return RES_COPY_FAILED;
258 }
259
260 fseek(src, 0, SEEK_END);
261 u64 sz = ftell(src);
262 rewind(src);
263
264 u8* buf = new u8[BUFFER_SIZE];
265 u64 offset = 0;
266 Result res = 0;
267
268 size_t slashpos = srcPath.rfind("/");
269 sink.startFile(srcPath.substr(slashpos + 1, srcPath.length() - slashpos - 1), sz);
270
271 // The save journal only holds `commitWriteLimit` bytes of uncommitted writes:
272 // a single file bigger than that must be committed partway through, or the
273 // commit at the end would overflow the journal and fail (#443, #297).
274 const bool toSaveDevice = dstPath.rfind("save:/", 0) == 0;
275 u64 journalPending = 0;
276
277 while (offset < sz) {
278 if (sink.cancelled()) {
279 break;
280 }
281
282 size_t count = fread((char*)buf, 1, BUFFER_SIZE, src);
283 if (count == 0) {
284 Logging::error("fread returned 0 for file {} at offset {}/{} with errno {}. Aborting copy.", srcPath, offset, sz, errno);
285 res = RES_COPY_FAILED;
286 break;
287 }
288
289 // commit *before* the write that would cross the limit, while the
290 // journal still has room for it
291 if (toSaveDevice && commitWriteLimit > 0 && journalPending + count > commitWriteLimit && journalPending > 0) {
292 if (fclose(dst) != 0) {
293 Logging::error("fclose before mid-file commit failed for {} with errno {}. Aborting copy.", dstPath, errno);
294 dst = NULL;
295 res = RES_COPY_FAILED;
296 break;
297 }
298 res = fsdevCommitDevice("save");
299 if (R_FAILED(res)) {
300 Logging::error("Mid-file commit of {} at offset {}/{} failed with result 0x{:08X}. Aborting copy.", dstPath, offset, sz, (u32)res);
301 dst = NULL;
302 break;
303 }

Callers

nothing calls this directly

Calls 6

errorFunction · 0.85
debugFunction · 0.85
startFileMethod · 0.45
cancelledMethod · 0.45
advanceBytesMethod · 0.45
finishFileMethod · 0.45

Tested by

no test coverage detected