1
2 /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
3 Copyright (c) 2006 - 2017 Thomas Schmitt <scdbackup@gmx.net>
4 Provided under GPL version 2 or later.
5 */
6
7 #ifdef HAVE_CONFIG_H
8 #include "../config.h"
9 #endif
10
11 #include "libburn.h"
12 #include "options.h"
13 #include "drive.h"
14 #include "transport.h"
15 #include "init.h"
16 #include "write.h"
17
18 /* ts A61007 */
19 /* #include <a ssert.h> */
20
21 #include <stdlib.h>
22 #include <string.h>
23 #include <stdio.h>
24
25 #include "libdax_msgs.h"
26 extern struct libdax_msgs *libdax_messenger;
27
28
burn_write_opts_new(struct burn_drive * drive)29 struct burn_write_opts *burn_write_opts_new(struct burn_drive *drive)
30 {
31 struct burn_write_opts *opts;
32
33 opts = calloc(1, sizeof(struct burn_write_opts));
34 if (opts == NULL) {
35 libdax_msgs_submit(libdax_messenger, -1, 0x00020111,
36 LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
37 "Could not allocate new auxiliary object", 0, 0);
38 return NULL;
39 }
40 opts->drive = drive;
41 opts->refcount = 1;
42 opts->write_type = BURN_WRITE_TAO;
43 opts->block_type = BURN_BLOCK_MODE1;
44 opts->toc_entry = NULL;
45 opts->toc_entries = 0;
46 opts->simulate = 0;
47 opts->underrun_proof = drive->mdata->p2a_valid > 0 &&
48 drive->mdata->underrun_proof;
49 opts->perform_opc = 1;
50 opts->obs = -1;
51
52 #ifdef Libburn_dvd_always_obs_paD
53 opts->obs_pad = 1;
54 #else
55 opts->obs_pad = 0;
56 #endif
57
58 opts->start_byte = -1;
59 opts->fill_up_media = 0;
60 opts->force_is_set = 0;
61 opts->do_stream_recording = 0;
62 opts->dvd_obs_override = 0;
63 opts->stdio_fsync_size = Libburn_stdio_fsync_limiT;
64 opts->text_packs = NULL;
65 opts->num_text_packs = 0;
66 opts->no_text_pack_crc_check = 0;
67 opts->has_mediacatalog = 0;
68 opts->format = BURN_CDROM;
69 opts->multi = 0;
70 opts->control = 0;
71 return opts;
72 }
73
burn_write_opts_free(struct burn_write_opts * opts)74 void burn_write_opts_free(struct burn_write_opts *opts)
75 {
76 if (--opts->refcount > 0)
77 return;
78 if (opts->text_packs != NULL)
79 free(opts->text_packs);
80 free(opts);
81 }
82
burn_write_opts_clone(struct burn_write_opts * from,struct burn_write_opts ** to,int flag)83 int burn_write_opts_clone(struct burn_write_opts *from,
84 struct burn_write_opts **to, int flag)
85 {
86 if (*to != NULL)
87 burn_write_opts_free(*to);
88 if (from == NULL)
89 return 1;
90 *to = calloc(1, sizeof(struct burn_write_opts));
91 if (*to == NULL) {
92 out_of_mem:;
93 libdax_msgs_submit(libdax_messenger, -1, 0x00000003,
94 LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
95 "Out of virtual memory", 0, 0);
96 return -1;
97 }
98 memcpy(*to, from, sizeof(struct burn_write_opts));
99 (*to)->text_packs = NULL;
100 (*to)->num_text_packs = 0;
101 if (from->text_packs != NULL && from->num_text_packs > 0) {
102 (*to)->text_packs = calloc(1, from->num_text_packs * 18);
103 if ((*to)->text_packs == NULL)
104 goto out_of_mem;
105 memcpy((*to)->text_packs, from->text_packs,
106 from->num_text_packs * 18);
107 }
108 (*to)->refcount= 1;
109 return 1;
110 }
111
burn_read_opts_new(struct burn_drive * drive)112 struct burn_read_opts *burn_read_opts_new(struct burn_drive *drive)
113 {
114 struct burn_read_opts *opts;
115
116 opts = calloc(1, sizeof(struct burn_read_opts));
117 opts->drive = drive;
118 opts->refcount = 1;
119 opts->raw = 0;
120 opts->c2errors = 0;
121 opts->subcodes_audio = 0;
122 opts->subcodes_data = 0;
123 opts->hardware_error_recovery = 0;
124 opts->report_recovered_errors = 0;
125 opts->transfer_damaged_blocks = 0;
126 opts->hardware_error_retries = 3;
127 opts->dap_bit = 0;
128
129 return opts;
130 }
131
burn_read_opts_free(struct burn_read_opts * opts)132 void burn_read_opts_free(struct burn_read_opts *opts)
133 {
134 if (--opts->refcount <= 0)
135 free(opts);
136 }
137
burn_write_opts_set_write_type(struct burn_write_opts * opts,enum burn_write_types write_type,int block_type)138 int burn_write_opts_set_write_type(struct burn_write_opts *opts,
139 enum burn_write_types write_type,
140 int block_type)
141 {
142 int sector_get_outmode(enum burn_write_types write_type,
143 enum burn_block_types block_type);
144 int spc_block_type(enum burn_block_types b);
145
146 /* ts A61007 */
147 if (! ( (write_type == BURN_WRITE_SAO && block_type == BURN_BLOCK_SAO)
148 || (opts->drive->block_types[write_type] & block_type) ) ) {
149 bad_combination:;
150 libdax_msgs_submit(libdax_messenger, -1, 0x00020112,
151 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
152 "Bad combination of write_type and block_type", 0, 0);
153 return 0;
154 }
155 /* ts A61007 : obsoleting Assert in sector.c:get_outmode() */
156 if (sector_get_outmode(write_type, (enum burn_block_types) block_type)
157 == -1)
158 goto bad_combination;
159 /* ts A61007 : obsoleting Assert in spc.c:spc_block_type() */
160 if (spc_block_type((enum burn_block_types) block_type) == -1)
161 goto bad_combination;
162
163 opts->write_type = write_type;
164 opts->block_type = block_type;
165 return 1;
166
167 /* a ssert(0); */
168 }
169
burn_write_opts_set_toc_entries(struct burn_write_opts * opts,int count,struct burn_toc_entry * toc_entries)170 void burn_write_opts_set_toc_entries(struct burn_write_opts *opts, int count,
171 struct burn_toc_entry *toc_entries)
172 {
173 opts->toc_entries = count;
174 opts->toc_entry = calloc(count, sizeof(struct burn_toc_entry));
175 memcpy(opts->toc_entry, &toc_entries,
176 sizeof(struct burn_toc_entry) * count);
177 }
178
burn_write_opts_set_format(struct burn_write_opts * opts,int format)179 void burn_write_opts_set_format(struct burn_write_opts *opts, int format)
180 {
181 opts->format = format;
182 }
183
burn_write_opts_set_simulate(struct burn_write_opts * opts,int sim)184 int burn_write_opts_set_simulate(struct burn_write_opts *opts, int sim)
185 {
186 opts->simulate = !!sim;
187 return 1;
188 }
189
burn_write_opts_set_underrun_proof(struct burn_write_opts * opts,int underrun_proof)190 int burn_write_opts_set_underrun_proof(struct burn_write_opts *opts,
191 int underrun_proof)
192 {
193 if (opts->drive->mdata->p2a_valid <= 0 ||
194 opts->drive->mdata->underrun_proof) {
195 opts->underrun_proof = underrun_proof;
196 return 1;
197 }
198 return 0;
199 }
200
burn_write_opts_set_perform_opc(struct burn_write_opts * opts,int opc)201 void burn_write_opts_set_perform_opc(struct burn_write_opts *opts, int opc)
202 {
203 opts->perform_opc = opc;
204 }
205
burn_write_opts_set_has_mediacatalog(struct burn_write_opts * opts,int has_mediacatalog)206 void burn_write_opts_set_has_mediacatalog(struct burn_write_opts *opts,
207 int has_mediacatalog)
208 {
209 opts->has_mediacatalog = has_mediacatalog;
210 }
211
burn_write_opts_set_mediacatalog(struct burn_write_opts * opts,unsigned char mediacatalog[13])212 void burn_write_opts_set_mediacatalog(struct burn_write_opts *opts,
213 unsigned char mediacatalog[13])
214 {
215 memcpy(opts->mediacatalog, mediacatalog, 13);
216 }
217
218
219 /* ts A61106 */
burn_write_opts_set_multi(struct burn_write_opts * opts,int multi)220 void burn_write_opts_set_multi(struct burn_write_opts *opts, int multi)
221 {
222 opts->multi = !!multi;
223 }
224
225
226 /* ts B31024 */
227 /* API */
burn_write_opts_set_fail21h_sev(struct burn_write_opts * opts,char * severity)228 void burn_write_opts_set_fail21h_sev(struct burn_write_opts *opts,
229 char *severity)
230 {
231 int ret, sevno;
232
233 ret = libdax_msgs__text_to_sev(severity, &sevno, 0);
234 if (ret <= 0)
235 opts->feat21h_fail_sev = 0;
236 else
237 opts->feat21h_fail_sev = sevno;
238 }
239
240
241 /* ts B11204 */
242 /* @param flag bit0=do not verify checksums
243 bit1= repair mismatching checksums
244 bit2= repair checksums if they are 00 00 with each pack
245 */
burn_write_opts_set_leadin_text(struct burn_write_opts * opts,unsigned char * text_packs,int num_packs,int flag)246 int burn_write_opts_set_leadin_text(struct burn_write_opts *opts,
247 unsigned char *text_packs,
248 int num_packs, int flag)
249 {
250 int ret;
251 unsigned char *pack_buffer = NULL;
252
253 if (num_packs > Libburn_leadin_cdtext_packs_maX ) {
254 libdax_msgs_submit(libdax_messenger, opts->drive->global_index,
255 0x0002018b,
256 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
257 "Too many CD-TEXT packs", 0, 0);
258 ret= 0; goto ex;
259 }
260
261 if (num_packs > 0)
262 BURN_ALLOC_MEM(pack_buffer, unsigned char, num_packs * 18);
263
264 if (opts->text_packs != NULL) {
265 free(opts->text_packs);
266 opts->text_packs = NULL;
267 }
268
269 if (flag & 1) {
270 opts->no_text_pack_crc_check = 1;
271 } else {
272 opts->no_text_pack_crc_check = 0;
273 ret = burn_cdtext_crc_mismatches(text_packs, num_packs,
274 (flag >> 1) & 3);
275 if (ret > 0) {
276 libdax_msgs_submit(libdax_messenger, -1, 0x0002018f,
277 LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
278 "CD-TEXT pack CRC mismatch", 0, 0);
279 ret = 0; goto ex;
280 } else if (ret < 0) {
281 libdax_msgs_submit(libdax_messenger, -1, 0x00020190,
282 LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
283 "CD-TEXT pack CRC mismatch had to be corrected",
284 0, 0);
285 }
286 }
287
288 if (num_packs > 0) {
289 memcpy(pack_buffer, text_packs, num_packs * 18);
290 opts->text_packs = pack_buffer;
291 pack_buffer = NULL;
292 }
293 opts->num_text_packs = num_packs;
294 ret = 1;
295 ex:;
296 BURN_FREE_MEM(pack_buffer);
297 return ret;
298 }
299
300
301 /* ts A61222 */
burn_write_opts_set_start_byte(struct burn_write_opts * opts,off_t value)302 void burn_write_opts_set_start_byte(struct burn_write_opts *opts, off_t value)
303 {
304 opts->start_byte = value;
305 }
306
307
308 /* ts A70207 API */
309 /** @param flag Bitfield for control purposes:
310 bit0= do not choose type but check the one that is already set
311 bit1= do not issue error messages via burn_msgs queue
312 */
burn_write_opts_auto_write_type(struct burn_write_opts * opts,struct burn_disc * disc,char reasons[BURN_REASONS_LEN],int flag)313 enum burn_write_types burn_write_opts_auto_write_type(
314 struct burn_write_opts *opts, struct burn_disc *disc,
315 char reasons[BURN_REASONS_LEN], int flag)
316 {
317 struct burn_multi_caps *caps = NULL;
318 struct burn_drive *d = opts->drive;
319 struct burn_disc_mode_demands demands;
320 enum burn_write_types wt;
321 int ret, would_do_sao = 0;
322 char *reason_pt;
323
324 reasons[0] = 0;
325
326 if (burn_drive_get_bd_r_pow(d)) {
327 strcat(reasons,
328 "MEDIA: unsuitable BD-R Pseudo Overwrite formatting, ");
329 return BURN_WRITE_NONE;
330 }
331 if (d->status != BURN_DISC_BLANK &&
332 d->status != BURN_DISC_APPENDABLE){
333 if (d->status == BURN_DISC_FULL)
334 strcat(reasons, "MEDIA: closed or not recordable, ");
335 else
336 strcat(reasons,"MEDIA: no writeable media detected, ");
337 if (!(flag & 3))
338 libdax_msgs_submit(libdax_messenger, d->global_index,
339 0x0002013a,
340 LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
341 "No suitable media detected", 0, 0);
342 return BURN_WRITE_NONE;
343 }
344 ret = burn_disc_get_write_mode_demands(disc, opts, &demands,
345 !!opts->fill_up_media);
346 if (ret <= 0) {
347 strcat(reasons, "cannot recognize job demands, ");
348 {wt = BURN_WRITE_NONE; goto ex;}
349 }
350 if (demands.exotic_track && !d->current_is_cd_profile) {
351 if (demands.audio)
352 strcat(reasons, "audio track prohibited by non-CD, ");
353 else
354 strcat(reasons, "exotic track prohibited by non-CD, ");
355 {wt = BURN_WRITE_NONE; goto ex;}
356 }
357 if ((flag & 1) && opts->write_type != BURN_WRITE_SAO)
358 goto try_tao;
359 reason_pt = reasons + strlen(reasons);
360 strcat(reasons, "SAO: ");
361 if (d->status != BURN_DISC_BLANK) {
362 strcat(reasons, "write type SAO works only on blank media, ");
363 goto try_tao;
364 }
365 burn_disc_free_multi_caps(&caps);
366 ret = burn_disc_get_multi_caps(d, BURN_WRITE_SAO, &caps, 0);
367 if (ret < 0) {
368 no_caps:;
369 strcat(reasons, "cannot inquire write mode capabilities, ");
370 {wt = BURN_WRITE_NONE; goto ex;}
371 } else if (ret == 0) {
372 strcat(reasons, "no SAO offered by drive and media, ");
373 goto no_sao;
374 }
375 if ((opts->multi || demands.multi_session) &&
376 !caps->multi_session)
377 strcat(reasons, "multi session capability lacking, ");
378 if (demands.will_append)
379 strcat(reasons, "appended session capability lacking, ");
380 if (demands.multi_track && !caps->multi_track)
381 strcat(reasons, "multi track capability lacking, ");
382 if (demands.unknown_track_size == 1 &&
383 (caps->might_do_sao == 1 || caps->might_do_sao == 3))
384 strcat(reasons, "track size unpredictable, ");
385 if (demands.mixed_mode)
386 strcat(reasons, "tracks of different modes mixed, ");
387 if (demands.exotic_track && !d->current_is_cd_profile)
388 strcat(reasons, "non-data track on non-cd, ");
389 else if (d->current_is_cd_profile)
390 if ((d->block_types[BURN_WRITE_TAO] & demands.block_types) !=
391 demands.block_types)
392 strcat(reasons, "drive dislikes block type, ");
393 if (d->current_is_cd_profile && opts->fill_up_media)
394 strcat(reasons, "cd sao cannot do media fill up yet, ");
395 if (strcmp(reason_pt, "SAO: ") != 0)
396 goto no_sao;
397 would_do_sao = 1;
398 if (demands.unknown_track_size == 2 && (!(flag & 1)) &&
399 (caps->might_do_sao == 1 || caps->might_do_sao == 3)) {
400 strcat(reasons, "would have to use default track sizes, ");
401 goto no_sao;
402 } else if (caps->might_do_sao >= 3 && !(flag & 1))
403 goto try_tao;
404 do_sao:;
405 if (caps->might_simulate == 0 && opts->simulate && !opts->force_is_set)
406 goto no_simulate;
407 if (!(flag & 1))
408 burn_write_opts_set_write_type(
409 opts, BURN_WRITE_SAO, BURN_BLOCK_SAO);
410 {wt = BURN_WRITE_SAO; goto ex;}
411 no_sao:;
412 try_tao:;
413 if (opts->num_text_packs > 0) {
414 strcat(reasons, "CD-TEXT: write type SAO required, ");
415 {wt = BURN_WRITE_NONE; goto ex;}
416 }
417 if ((flag & 1) && opts->write_type != BURN_WRITE_TAO)
418 goto try_raw;
419 reason_pt = reasons + strlen(reasons);
420 strcat(reasons, "TAO: ");
421 burn_disc_free_multi_caps(&caps);
422 ret = burn_disc_get_multi_caps(d, BURN_WRITE_TAO, &caps, 0);
423 if (ret < 0)
424 goto no_caps;
425 if (ret == 0) {
426 strcat(reasons, "no TAO offered by drive and media, ");
427 goto no_tao;
428 }
429 if ((opts->multi || demands.multi_session) && !caps->multi_session)
430 strcat(reasons, "multi session capability lacking, ");
431 if (demands.multi_track && !caps->multi_track)
432 strcat(reasons, "multi track capability lacking, ");
433 if (demands.exotic_track && !d->current_is_cd_profile)
434 strcat(reasons, "non-data track on non-cd, ");
435 if (d->current_is_cd_profile && !opts->force_is_set)
436 if ((d->block_types[BURN_WRITE_TAO] & demands.block_types) !=
437 demands.block_types)
438 strcat(reasons, "drive dislikes block type, ");
439 if (strcmp(reason_pt, "TAO: ") != 0)
440 goto no_tao;
441 /* ( TAO data/audio block size will be handled automatically ) */
442 if (caps->might_simulate == 0 && opts->simulate && !opts->force_is_set)
443 goto no_simulate;
444 if (!(flag & 1))
445 burn_write_opts_set_write_type(
446 opts, BURN_WRITE_TAO, BURN_BLOCK_MODE1);
447 {wt = BURN_WRITE_TAO; goto ex;}
448 no_tao:;
449 if (would_do_sao && !(flag & 1))
450 goto do_sao;
451 if (!d->current_is_cd_profile)
452 goto no_write_mode;
453 try_raw:;
454 if ((flag & 1) && opts->write_type != BURN_WRITE_RAW)
455 goto no_write_mode;
456
457 if (!(flag & 1)) /* For now: no automatic raw write modes */
458 goto no_write_mode;
459
460 reason_pt = reasons + strlen(reasons);
461 strcat(reasons, "RAW: ");
462 if (!d->current_is_cd_profile)
463 strcat(reasons, "write type RAW prohibited by non-cd, ");
464 else if (d->status != BURN_DISC_BLANK)
465 strcat(reasons, "write type RAW works only on blank media, ");
466 else if ((d->block_types[BURN_WRITE_TAO] & demands.block_types) !=
467 demands.block_types)
468 strcat(reasons, "drive dislikes block type, ");
469 if (strcmp(reason_pt, "RAW: ") != 0)
470 goto no_write_mode;
471 if (!opts->force_is_set)
472 goto no_simulate;
473
474 /* For now: no setting of raw write modes */
475
476 {wt = BURN_WRITE_RAW; goto ex;}
477
478 no_write_mode:;
479 {wt = BURN_WRITE_NONE; goto ex;}
480
481 no_simulate:;
482 strcat(reasons,
483 "simulation of write job not supported by drive and media, ");
484 {wt = BURN_WRITE_NONE; goto ex;}
485
486 ex:;
487 burn_disc_free_multi_caps(&caps);
488 if (wt == BURN_WRITE_NONE && !(flag & 3)) {
489 libdax_msgs_submit(libdax_messenger, d->global_index,
490 0x0002012b,
491 LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
492 "Drive offers no suitable write mode with this job",
493 0, 0);
494 }
495 return wt;
496 }
497
498
499 /* ts A70213 : new API function */
burn_write_opts_set_fillup(struct burn_write_opts * opts,int fill_up_media)500 void burn_write_opts_set_fillup(struct burn_write_opts *opts,int fill_up_media)
501 {
502 opts->fill_up_media = !!fill_up_media;
503 return;
504 }
505
506
507 /* ts A70303: API */
burn_write_opts_set_force(struct burn_write_opts * opts,int use_force)508 void burn_write_opts_set_force(struct burn_write_opts *opts, int use_force)
509 {
510 opts->force_is_set = !!use_force;
511 }
512
513
514 /* ts A80412: API */
burn_write_opts_set_stream_recording(struct burn_write_opts * opts,int value)515 void burn_write_opts_set_stream_recording(struct burn_write_opts *opts,
516 int value)
517 {
518 opts->do_stream_recording = value;
519 }
520
521
522 /* ts A91115: API */
burn_write_opts_set_dvd_obs(struct burn_write_opts * opts,int obs)523 void burn_write_opts_set_dvd_obs(struct burn_write_opts *opts, int obs)
524 {
525 if (obs != 0 && obs != 32 * 1024 && obs != 64 * 1024)
526 return;
527 opts->dvd_obs_override = obs;
528 }
529
530
531 /* ts B20406: API */
burn_write_opts_set_obs_pad(struct burn_write_opts * opts,int pad)532 void burn_write_opts_set_obs_pad(struct burn_write_opts *opts, int pad)
533 {
534 opts->obs_pad = 2 * !!pad;
535 }
536
537
538 /* ts A91115: API */
burn_write_opts_set_stdio_fsync(struct burn_write_opts * opts,int rhythm)539 void burn_write_opts_set_stdio_fsync(struct burn_write_opts *opts, int rhythm)
540 {
541 if (rhythm == -1)
542 opts->stdio_fsync_size = -1; /* never */
543 else if (rhythm == 0)
544 opts->stdio_fsync_size = Libburn_stdio_fsync_limiT;
545 else if (rhythm == 1)
546 opts->stdio_fsync_size = 0; /* only at end of writing */
547 else if (rhythm >= 32)
548 opts->stdio_fsync_size = rhythm;
549 }
550
551
552 /* ts A70901: API */
burn_write_opts_get_drive(struct burn_write_opts * opts)553 struct burn_drive *burn_write_opts_get_drive(struct burn_write_opts *opts)
554 {
555 return opts->drive;
556 }
557
558
burn_read_opts_set_raw(struct burn_read_opts * opts,int raw)559 void burn_read_opts_set_raw(struct burn_read_opts *opts, int raw)
560 {
561 opts->raw = raw;
562 }
563
burn_read_opts_set_c2errors(struct burn_read_opts * opts,int c2errors)564 void burn_read_opts_set_c2errors(struct burn_read_opts *opts, int c2errors)
565 {
566 opts->c2errors = c2errors;
567 }
568
burn_read_opts_read_subcodes_audio(struct burn_read_opts * opts,int subcodes_audio)569 void burn_read_opts_read_subcodes_audio(struct burn_read_opts *opts,
570 int subcodes_audio)
571 {
572 opts->subcodes_audio = subcodes_audio;
573 }
574
burn_read_opts_read_subcodes_data(struct burn_read_opts * opts,int subcodes_data)575 void burn_read_opts_read_subcodes_data(struct burn_read_opts *opts,
576 int subcodes_data)
577 {
578 opts->subcodes_data = subcodes_data;
579 }
580
burn_read_opts_set_hardware_error_recovery(struct burn_read_opts * opts,int hardware_error_recovery)581 void burn_read_opts_set_hardware_error_recovery(struct burn_read_opts *opts,
582 int hardware_error_recovery)
583 {
584 opts->hardware_error_recovery = hardware_error_recovery;
585 }
586
burn_read_opts_report_recovered_errors(struct burn_read_opts * opts,int report_recovered_errors)587 void burn_read_opts_report_recovered_errors(struct burn_read_opts *opts,
588 int report_recovered_errors)
589 {
590 opts->report_recovered_errors = report_recovered_errors;
591 }
592
burn_read_opts_transfer_damaged_blocks(struct burn_read_opts * opts,int transfer_damaged_blocks)593 void burn_read_opts_transfer_damaged_blocks(struct burn_read_opts *opts,
594 int transfer_damaged_blocks)
595 {
596 opts->transfer_damaged_blocks = transfer_damaged_blocks;
597 }
598
burn_read_opts_set_hardware_error_retries(struct burn_read_opts * opts,unsigned char hardware_error_retries)599 void burn_read_opts_set_hardware_error_retries(struct burn_read_opts *opts,
600 unsigned char
601 hardware_error_retries)
602 {
603 opts->hardware_error_retries = hardware_error_retries;
604 }
605
606