static int tar_export_process(TarExport *e) { ssize_t l; int r; assert(e); if (!e->tried_splice && e->compress.type == IMPORT_COMPRESS_UNCOMPRESSED) { l = splice(e->tar_fd, NULL, e->output_fd, NULL, COPY_BUFFER_SIZE, 0); if (l < 0) { if (errno == EAGAIN) return 0; e->tried_splice = true; } else if (l == 0) { r = 0; goto finish; } else { e->written_uncompressed += l; e->written_compressed += l; tar_export_report_progress(e); return 0; } } while (e->buffer_size <= 0) { uint8_t input[COPY_BUFFER_SIZE]; if (e->eof) { r = 0; goto finish; } l = read(e->tar_fd, input, sizeof(input)); if (l < 0) { r = log_error_errno(errno, "Failed to read tar file: %m"); goto finish; } if (l == 0) { e->eof = true; r = import_compress_finish(&e->compress, &e->buffer, &e->buffer_size, &e->buffer_allocated); } else { e->written_uncompressed += l; r = import_compress(&e->compress, input, l, &e->buffer, &e->buffer_size, &e->buffer_allocated); } if (r < 0) { r = log_error_errno(r, "Failed to encode: %m"); goto finish; } } l = write(e->output_fd, e->buffer, e->buffer_size); if (l < 0) { if (errno == EAGAIN) return 0; r = log_error_errno(errno, "Failed to write output file: %m"); goto finish; } assert((size_t) l <= e->buffer_size); memmove(e->buffer, (uint8_t*) e->buffer + l, e->buffer_size - l); e->buffer_size -= l; e->written_compressed += l; tar_export_report_progress(e); return 0; finish: if (e->on_finished) e->on_finished(e, r, e->userdata); else sd_event_exit(e->event, r); return 0; }
static int raw_export_process(RawExport *e) { ssize_t l; int r; assert(e); if (!e->tried_reflink && e->compress.type == IMPORT_COMPRESS_UNCOMPRESSED) { /* If we shall take an uncompressed snapshot we can * reflink source to destination directly. Let's see * if this works. */ r = btrfs_reflink(e->input_fd, e->output_fd); if (r >= 0) { r = 0; goto finish; } e->tried_reflink = true; } if (!e->tried_sendfile && e->compress.type == IMPORT_COMPRESS_UNCOMPRESSED) { l = sendfile(e->output_fd, e->input_fd, NULL, COPY_BUFFER_SIZE); if (l < 0) { if (errno == EAGAIN) return 0; e->tried_sendfile = true; } else if (l == 0) { r = 0; goto finish; } else { e->written_uncompressed += l; e->written_compressed += l; raw_export_report_progress(e); return 0; } } while (e->buffer_size <= 0) { uint8_t input[COPY_BUFFER_SIZE]; if (e->eof) { r = 0; goto finish; } l = read(e->input_fd, input, sizeof(input)); if (l < 0) { r = log_error_errno(errno, "Failed to read raw file: %m"); goto finish; } if (l == 0) { e->eof = true; r = import_compress_finish(&e->compress, &e->buffer, &e->buffer_size, &e->buffer_allocated); } else { e->written_uncompressed += l; r = import_compress(&e->compress, input, l, &e->buffer, &e->buffer_size, &e->buffer_allocated); } if (r < 0) { r = log_error_errno(r, "Failed to encode: %m"); goto finish; } } l = write(e->output_fd, e->buffer, e->buffer_size); if (l < 0) { if (errno == EAGAIN) return 0; r = log_error_errno(errno, "Failed to write output file: %m"); goto finish; } assert((size_t) l <= e->buffer_size); memmove(e->buffer, (uint8_t*) e->buffer + l, e->buffer_size - l); e->buffer_size -= l; e->written_compressed += l; raw_export_report_progress(e); return 0; finish: if (r >= 0) { (void) copy_times(e->input_fd, e->output_fd); (void) copy_xattr(e->input_fd, e->output_fd); } if (e->on_finished) e->on_finished(e, r, e->userdata); else sd_event_exit(e->event, r); return 0; }