00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00020
00021
00022
00023
00024
00025
00026
00027
00028
00029
00030
00031
00032
00033
00034
00035
00036
00037
00038
00039
00040
00041
00042
00043
00044
00045
00046
00047
00048
00049
00050
00051
00052
00053
00054
00055
00056
00057
00058
00059
00060
00061
00062
00063
00064
00065
00066
00067 #include "../libburn/libburn.h"
00068
00069
00070 #include <stdio.h>
00071 #include <ctype.h>
00072 #include <sys/types.h>
00073 #include <unistd.h>
00074 #include <string.h>
00075 #include <stdlib.h>
00076 #include <time.h>
00077 #include <errno.h>
00078 #include <sys/stat.h>
00079 #include <fcntl.h>
00080
00081
00082
00083
00084
00085
00086
00087
00088
00089 static struct burn_drive_info *drive_list;
00090
00091
00092
00093 static unsigned int drive_count;
00094
00095
00096
00097 static int drive_is_grabbed = 0;
00098
00099
00100 static int current_profile= -1;
00101 static char current_profile_name[80]= {""};
00102
00103
00104
00105
00106 int libburner_aquire_by_adr(char *drive_adr);
00107 int libburner_aquire_by_driveno(int *drive_no);
00108
00109
00110
00111
00112
00113
00114
00115
00116
00117
00118
00119
00120
00121
00122
00123 int libburner_aquire_drive(char *drive_adr, int *driveno)
00124 {
00125 int ret;
00126
00127 if(drive_adr != NULL && drive_adr[0] != 0)
00128 ret = libburner_aquire_by_adr(drive_adr);
00129 else
00130 ret = libburner_aquire_by_driveno(driveno);
00131 if (ret <= 0 || *driveno <= 0)
00132 return ret;
00133 burn_disc_get_profile(drive_list[0].drive, ¤t_profile,
00134 current_profile_name);
00135 if (current_profile_name[0])
00136 printf("Detected media type: %s\n", current_profile_name);
00137 return 1;
00138 }
00139
00140
00141
00142
00143
00144
00145 int libburner_aquire_by_adr(char *drive_adr)
00146 {
00147 int ret;
00148 char libburn_drive_adr[BURN_DRIVE_ADR_LEN];
00149
00150
00151 if (strncmp(drive_adr, "stdio:/dev/fd/", 14) == 0 ||
00152 strcmp(drive_adr, "stdio:-") == 0) {
00153 fprintf(stderr, "Will not work with pseudo-drive '%s'\n",
00154 drive_adr);
00155 return 0;
00156 }
00157
00158
00159 ret = burn_drive_convert_fs_adr(drive_adr, libburn_drive_adr);
00160 if (ret<=0) {
00161 fprintf(stderr, "Address does not lead to a CD burner: '%s'\n",
00162 drive_adr);
00163 return 0;
00164 }
00165 fprintf(stderr,"Aquiring drive '%s' ...\n", libburn_drive_adr);
00166 ret = burn_drive_scan_and_grab(&drive_list, libburn_drive_adr, 1);
00167 if (ret <= 0) {
00168 fprintf(stderr,"FAILURE with persistent drive address '%s'\n",
00169 libburn_drive_adr);
00170 } else {
00171 fprintf(stderr,"Done\n");
00172 drive_is_grabbed = 1;
00173 }
00174 return ret;
00175 }
00176
00177
00178
00179
00180
00181
00182
00183
00184
00185
00186
00187
00188
00189
00190 int libburner_aquire_by_driveno(int *driveno)
00191 {
00192 char adr[BURN_DRIVE_ADR_LEN];
00193 int ret, i;
00194
00195 printf("Beginning to scan for devices ...\n");
00196 while (!burn_drive_scan(&drive_list, &drive_count))
00197 usleep(100002);
00198 if (drive_count <= 0 && *driveno >= 0) {
00199 printf("FAILED (no drives found)\n");
00200 return 0;
00201 }
00202 printf("Done\n");
00203
00204
00205
00206
00207
00208
00209
00210
00211
00212
00213
00214
00215
00216
00217
00218 printf("\nOverview of accessible drives (%d found) :\n",
00219 drive_count);
00220 printf("-----------------------------------------------------------------------------\n");
00221 for (i = 0; i < drive_count; i++) {
00222 if (burn_drive_get_adr(&(drive_list[i]), adr) <=0)
00223 strcpy(adr, "-get_adr_failed-");
00224 printf("%d --drive '%s' : '%s' '%s'\n",
00225 i,adr,drive_list[i].vendor,drive_list[i].product);
00226 }
00227 printf("-----------------------------------------------------------------------------\n\n");
00228
00229
00230
00231
00232
00233
00234
00235
00236
00237
00238
00239
00240
00241
00242
00243
00244
00245
00246
00247
00248
00249
00250
00251
00252
00253
00254 if (*driveno < 0) {
00255 printf("Pseudo-drive \"-\" given : bus scanning done.\n");
00256 return 2;
00257 }
00258 if (drive_count <= *driveno) {
00259 fprintf(stderr,
00260 "Found only %d drives. Number %d not available.\n",
00261 drive_count, *driveno);
00262 return 0;
00263 }
00264
00265
00266 for (i = 0; i < drive_count; i++) {
00267 if (i == *driveno)
00268 continue;
00269 ret = burn_drive_info_forget(&(drive_list[i]),0);
00270 if (ret != 1)
00271 fprintf(stderr, "Cannot drop drive %d. Please report \"ret=%d\" to libburn-hackers@pykix.org\n",
00272 i, ret);
00273 else
00274 printf("Dropped unwanted drive %d\n",i);
00275 }
00276
00277 ret= burn_drive_grab(drive_list[*driveno].drive, 1);
00278 if (ret != 1)
00279 return 0;
00280 drive_is_grabbed = 1;
00281 return 1;
00282 }
00283
00284
00285
00286
00287
00288
00289
00290
00291
00292
00293 int libburner_blank_disc(struct burn_drive *drive, int blank_fast)
00294 {
00295 enum burn_disc_status disc_state;
00296 struct burn_progress p;
00297 double percent = 1.0;
00298
00299 disc_state = burn_disc_get_status(drive);
00300 printf(
00301 "Drive media status: %d (see libburn/libburn.h BURN_DISC_*)\n",
00302 disc_state);
00303 if (current_profile == 0x13) {
00304 ;
00305 } else if (disc_state == BURN_DISC_BLANK) {
00306 fprintf(stderr,
00307 "IDLE: Blank media detected. Will leave it untouched\n");
00308 return 2;
00309 } else if (disc_state == BURN_DISC_FULL ||
00310 disc_state == BURN_DISC_APPENDABLE) {
00311 ;
00312 } else if (disc_state == BURN_DISC_EMPTY) {
00313 fprintf(stderr,"FATAL: No media detected in drive\n");
00314 return 0;
00315 } else {
00316 fprintf(stderr,
00317 "FATAL: Unsuitable drive and media state\n");
00318 return 0;
00319 }
00320 if(!burn_disc_erasable(drive)) {
00321 fprintf(stderr,
00322 "FATAL : Media is not of erasable type\n");
00323 return 0;
00324 }
00325
00326 burn_set_signal_handling("libburner : ", NULL, 0x30);
00327
00328 printf("Beginning to %s-blank media.\n", (blank_fast?"fast":"full"));
00329 burn_disc_erase(drive, blank_fast);
00330
00331 sleep(1);
00332 while (burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) {
00333 if(p.sectors>0 && p.sector>=0)
00334 percent = 1.0 + ((double) p.sector+1.0)
00335 / ((double) p.sectors) * 98.0;
00336 printf("Blanking ( %.1f%% done )\n", percent);
00337 sleep(1);
00338 }
00339 if (burn_is_aborting(0) > 0)
00340 return -1;
00341
00342 burn_set_signal_handling("libburner : ", NULL, 0x0);
00343 printf("Done\n");
00344 return 1;
00345 }
00346
00347
00348
00349
00350
00351
00352
00353
00354
00355
00356
00357
00358
00359
00360 int libburner_format(struct burn_drive *drive)
00361 {
00362 struct burn_progress p;
00363 double percent = 1.0;
00364 int ret, status, num_formats, format_flag= 0;
00365 off_t size = 0;
00366 unsigned dummy;
00367 enum burn_disc_status disc_state;
00368
00369 if (current_profile == 0x13) {
00370 fprintf(stderr, "IDLE: DVD-RW media is already formatted\n");
00371 return 2;
00372 } else if (current_profile == 0x41 || current_profile == 0x43) {
00373 disc_state = burn_disc_get_status(drive);
00374 if (disc_state != BURN_DISC_BLANK && current_profile == 0x41) {
00375 fprintf(stderr,
00376 "FATAL: BD-R is not blank. Cannot format.\n");
00377 return 0;
00378 }
00379 ret = burn_disc_get_formats(drive, &status, &size, &dummy,
00380 &num_formats);
00381 if (ret > 0 && status != BURN_FORMAT_IS_UNFORMATTED) {
00382 fprintf(stderr,
00383 "IDLE: BD media is already formatted\n");
00384 return 2;
00385 }
00386 size = 0;
00387 format_flag = 3<<1;
00388 } else if (current_profile == 0x14) {
00389 size = 128 * 1024 * 1024;
00390 format_flag = 1;
00391 } else {
00392 fprintf(stderr, "FATAL: Can only format DVD-RW or BD\n");
00393 return 0;
00394 }
00395 burn_set_signal_handling("libburner : ", NULL, 0x30);
00396
00397 printf("Beginning to format media.\n");
00398 burn_disc_format(drive, size, format_flag);
00399
00400 sleep(1);
00401 while (burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) {
00402 if(p.sectors>0 && p.sector>=0)
00403 percent = 1.0 + ((double) p.sector+1.0)
00404 / ((double) p.sectors) * 98.0;
00405 printf("Formatting ( %.1f%% done )\n", percent);
00406 sleep(1);
00407 }
00408 if (burn_is_aborting(0) > 0)
00409 return -1;
00410 burn_set_signal_handling("libburner : ", NULL, 0x0);
00411 burn_disc_get_profile(drive_list[0].drive, ¤t_profile,
00412 current_profile_name);
00413 if (current_profile == 0x14 || current_profile == 0x13)
00414 printf("Media type now: %4.4xh \"%s\"\n",
00415 current_profile, current_profile_name);
00416 if (current_profile == 0x14) {
00417 fprintf(stderr,
00418 "FATAL: Failed to change media profile to desired value\n");
00419 return 0;
00420 }
00421 return 1;
00422 }
00423
00424
00425
00426
00427
00428
00429
00430
00431
00432
00433
00434
00435
00436
00437
00438
00439
00440 int libburner_payload(struct burn_drive *drive,
00441 char source_adr[][4096], int source_adr_count,
00442 int multi, int simulate_burn, int all_tracks_type)
00443 {
00444 struct burn_source *data_src, *fifo_src[99];
00445 struct burn_disc *target_disc;
00446 struct burn_session *session;
00447 struct burn_write_opts *burn_options;
00448 enum burn_disc_status disc_state;
00449 struct burn_track *track, *tracklist[99];
00450 struct burn_progress progress;
00451 time_t start_time;
00452 int last_sector = 0, padding = 0, trackno, unpredicted_size = 0, fd;
00453 int fifo_chunksize = 2352, fifo_chunks = 1783;
00454 off_t fixed_size;
00455 char *adr, reasons[BURN_REASONS_LEN];
00456 struct stat stbuf;
00457
00458 if (all_tracks_type != BURN_AUDIO) {
00459 all_tracks_type = BURN_MODE1;
00460
00461 padding = 300*1024;
00462 fifo_chunksize = 2048;
00463 fifo_chunks = 2048;
00464 }
00465
00466 target_disc = burn_disc_create();
00467 session = burn_session_create();
00468 burn_disc_add_session(target_disc, session, BURN_POS_END);
00469
00470 for (trackno = 0 ; trackno < source_adr_count; trackno++) {
00471 tracklist[trackno] = track = burn_track_create();
00472 burn_track_define_data(track, 0, padding, 1, all_tracks_type);
00473
00474
00475 adr = source_adr[trackno];
00476 fixed_size = 0;
00477 if (adr[0] == '-' && adr[1] == 0) {
00478 fd = 0;
00479 } else {
00480 fd = open(adr, O_RDONLY);
00481 if (fd>=0)
00482 if (fstat(fd,&stbuf)!=-1)
00483 if((stbuf.st_mode&S_IFMT)==S_IFREG)
00484 fixed_size = stbuf.st_size;
00485 }
00486 if (fixed_size==0)
00487 unpredicted_size = 1;
00488
00489
00490 data_src = NULL;
00491 if (fd>=0)
00492 data_src = burn_fd_source_new(fd, -1, fixed_size);
00493 if (data_src == NULL) {
00494 fprintf(stderr,
00495 "FATAL: Could not open data source '%s'.\n",adr);
00496 if(errno!=0)
00497 fprintf(stderr,"(Most recent system error: %s )\n",
00498 strerror(errno));
00499 return 0;
00500 }
00501
00502 fifo_src[trackno] = burn_fifo_source_new(data_src,
00503 fifo_chunksize, fifo_chunks, 0);
00504 if (fifo_src[trackno] == NULL) {
00505 fprintf(stderr,
00506 "FATAL: Could not create fifo object of 4 MB\n");
00507 return 0;
00508 }
00509
00510
00511 if (burn_track_set_source(track, fifo_src[trackno])
00512 != BURN_SOURCE_OK) {
00513 fprintf(stderr,
00514 "FATAL: Cannot attach source object to track object\n");
00515 return 0;
00516 }
00517
00518 burn_session_add_track(session, track, BURN_POS_END);
00519 printf("Track %d : source is '%s'\n", trackno+1, adr);
00520
00521
00522 burn_source_free(data_src);
00523
00524 }
00525
00526
00527 disc_state = burn_disc_get_status(drive);
00528 if (disc_state != BURN_DISC_BLANK &&
00529 disc_state != BURN_DISC_APPENDABLE) {
00530 if (disc_state == BURN_DISC_FULL) {
00531 fprintf(stderr, "FATAL: Closed media with data detected. Need blank or appendable media.\n");
00532 if (burn_disc_erasable(drive))
00533 fprintf(stderr, "HINT: Try --blank_fast\n\n");
00534 } else if (disc_state == BURN_DISC_EMPTY)
00535 fprintf(stderr,"FATAL: No media detected in drive\n");
00536 else
00537 fprintf(stderr,
00538 "FATAL: Cannot recognize state of drive and media\n");
00539 return 0;
00540 }
00541
00542 burn_options = burn_write_opts_new(drive);
00543 burn_write_opts_set_perform_opc(burn_options, 0);
00544 burn_write_opts_set_multi(burn_options, !!multi);
00545 if(simulate_burn)
00546 printf("\n*** Will TRY to SIMULATE burning ***\n\n");
00547 burn_write_opts_set_simulate(burn_options, simulate_burn);
00548 burn_drive_set_speed(drive, 0, 0);
00549 burn_write_opts_set_underrun_proof(burn_options, 1);
00550 if (burn_write_opts_auto_write_type(burn_options, target_disc,
00551 reasons, 0) == BURN_WRITE_NONE) {
00552 fprintf(stderr, "FATAL: Failed to find a suitable write mode with this media.\n");
00553 fprintf(stderr, "Reasons given:\n%s\n", reasons);
00554 return 0;
00555 }
00556 burn_set_signal_handling("libburner : ", NULL, 0x30);
00557
00558 printf("Burning starts. With e.g. 4x media expect up to a minute of zero progress.\n");
00559 start_time = time(0);
00560 burn_disc_write(burn_options, target_disc);
00561
00562 burn_write_opts_free(burn_options);
00563 while (burn_drive_get_status(drive, NULL) == BURN_DRIVE_SPAWNING)
00564 usleep(100002);
00565 while (burn_drive_get_status(drive, &progress) != BURN_DRIVE_IDLE) {
00566 if (progress.sectors <= 0 ||
00567 (progress.sector >= progress.sectors - 1 &&
00568 !unpredicted_size) ||
00569 (unpredicted_size && progress.sector == last_sector))
00570 printf(
00571 "Thank you for being patient since %d seconds.",
00572 (int) (time(0) - start_time));
00573 else if(unpredicted_size)
00574 printf("Track %d : sector %d", progress.track+1,
00575 progress.sector);
00576 else
00577 printf("Track %d : sector %d of %d",progress.track+1,
00578 progress.sector, progress.sectors);
00579 last_sector = progress.sector;
00580 if (progress.track >= 0 && progress.track < source_adr_count) {
00581 int size, free_bytes, ret;
00582 char *status_text;
00583
00584 ret = burn_fifo_inquire_status(
00585 fifo_src[progress.track], &size, &free_bytes,
00586 &status_text);
00587 if (ret >= 0 )
00588 printf(" [fifo %s, %2d%% fill]", status_text,
00589 (int) (100.0 - 100.0 *
00590 ((double) free_bytes) /
00591 (double) size));
00592 }
00593 printf("\n");
00594 sleep(1);
00595 }
00596 printf("\n");
00597
00598 for (trackno = 0 ; trackno < source_adr_count; trackno++) {
00599 burn_source_free(fifo_src[trackno]);
00600 burn_track_free(tracklist[trackno]);
00601 }
00602 burn_session_free(session);
00603 burn_disc_free(target_disc);
00604 if (burn_is_aborting(0) > 0)
00605 return -1;
00606 if (multi && current_profile != 0x1a && current_profile != 0x13 &&
00607 current_profile != 0x12 && current_profile != 0x43)
00608
00609 printf("NOTE: Media left appendable.\n");
00610 if (simulate_burn)
00611 printf("\n*** Did TRY to SIMULATE burning ***\n\n");
00612 return 1;
00613 }
00614
00615
00616
00617 static char drive_adr[BURN_DRIVE_ADR_LEN] = {""};
00618 static int driveno = 0;
00619 static int do_blank = 0;
00620 static char source_adr[99][4096];
00621 static int source_adr_count = 0;
00622 static int do_multi = 0;
00623 static int simulate_burn = 0;
00624 static int all_tracks_type = BURN_MODE1;
00625
00626
00627
00628
00629 int libburner_setup(int argc, char **argv)
00630 {
00631 int i, insuffient_parameters = 0, print_help = 0;
00632
00633 for (i = 1; i < argc; ++i) {
00634 if (!strcmp(argv[i], "--audio")) {
00635 all_tracks_type = BURN_AUDIO;
00636
00637 } else if (!strcmp(argv[i], "--blank_fast")) {
00638 do_blank = 1;
00639
00640 } else if (!strcmp(argv[i], "--blank_full")) {
00641 do_blank = 2;
00642
00643 } else if (!strcmp(argv[i], "--burn_for_real")) {
00644 simulate_burn = 0;
00645
00646 } else if (!strcmp(argv[i], "--drive")) {
00647 ++i;
00648 if (i >= argc) {
00649 fprintf(stderr,"--drive requires an argument\n");
00650 return 1;
00651 } else if (strcmp(argv[i], "-") == 0) {
00652 drive_adr[0] = 0;
00653 driveno = -1;
00654 } else if (isdigit(argv[i][0])) {
00655 drive_adr[0] = 0;
00656 driveno = atoi(argv[i]);
00657 } else {
00658 if(strlen(argv[i]) >= BURN_DRIVE_ADR_LEN) {
00659 fprintf(stderr,"--drive address too long (max. %d)\n",
00660 BURN_DRIVE_ADR_LEN-1);
00661 return 2;
00662 }
00663 strcpy(drive_adr, argv[i]);
00664 }
00665 } else if ((!strcmp(argv[i], "--format_overwrite")) ||
00666 (!strcmp(argv[i], "--format"))) {
00667 do_blank = 101;
00668
00669 } else if (!strcmp(argv[i], "--multi")) {
00670 do_multi = 1;
00671
00672 } else if (!strcmp(argv[i], "--stdin_size")) {
00673 i++;
00674
00675 } else if (!strcmp(argv[i], "--try_to_simulate")) {
00676 simulate_burn = 1;
00677
00678 } else if (!strcmp(argv[i], "--help")) {
00679 print_help = 1;
00680
00681 } else if (!strncmp(argv[i], "--",2)) {
00682 fprintf(stderr, "Unidentified option: %s\n", argv[i]);
00683 return 7;
00684 } else {
00685 if(strlen(argv[i]) >= 4096) {
00686 fprintf(stderr, "Source address too long (max. %d)\n", 4096-1);
00687 return 5;
00688 }
00689 if(source_adr_count >= 99) {
00690 fprintf(stderr, "Too many tracks (max. 99)\n");
00691 return 6;
00692 }
00693 strcpy(source_adr[source_adr_count], argv[i]);
00694 source_adr_count++;
00695 }
00696 }
00697 insuffient_parameters = 1;
00698 if (driveno < 0)
00699 insuffient_parameters = 0;
00700 if (source_adr_count > 0)
00701 insuffient_parameters = 0;
00702 if (do_blank)
00703 insuffient_parameters = 0;
00704 if (print_help || insuffient_parameters ) {
00705 printf("Usage: %s\n", argv[0]);
00706 printf(" [--drive <address>|<driveno>|\"-\"] [--audio]\n");
00707 printf(" [--blank_fast|--blank_full|--format] [--try_to_simulate]\n");
00708 printf(" [--multi] [<one or more imagefiles>|\"-\"]\n");
00709 printf("Examples\n");
00710 printf("A bus scan (needs rw-permissions to see a drive):\n");
00711 printf(" %s --drive -\n",argv[0]);
00712 printf("Burn a file to drive chosen by number, leave appendable:\n");
00713 printf(" %s --drive 0 --multi my_image_file\n", argv[0]);
00714 printf("Burn a file to drive chosen by persistent address, close:\n");
00715 printf(" %s --drive /dev/hdc my_image_file\n", argv[0]);
00716 printf("Blank a used CD-RW (is combinable with burning in one run):\n");
00717 printf(" %s --drive /dev/hdc --blank_fast\n",argv[0]);
00718 printf("Blank a used DVD-RW (is combinable with burning in one run):\n");
00719 printf(" %s --drive /dev/hdc --blank_full\n",argv[0]);
00720 printf("Format a DVD-RW, BD-RE or BD-R:\n");
00721 printf(" %s --drive /dev/hdc --format\n", argv[0]);
00722 printf("Burn two audio tracks (to CD only):\n");
00723 printf(" lame --decode -t /path/to/track1.mp3 track1.cd\n");
00724 printf(" test/dewav /path/to/track2.wav -o track2.cd\n");
00725 printf(" %s --drive /dev/hdc --audio track1.cd track2.cd\n", argv[0]);
00726 printf("Burn a compressed afio archive on-the-fly:\n");
00727 printf(" ( cd my_directory ; find . -print | afio -oZ - ) | \\\n");
00728 printf(" %s --drive /dev/hdc -\n", argv[0]);
00729 printf("To be read from *not mounted* media via: afio -tvZ /dev/hdc\n");
00730 if (insuffient_parameters)
00731 return 6;
00732 }
00733 return 0;
00734 }
00735
00736
00737 int main(int argc, char **argv)
00738 {
00739 int ret;
00740
00741
00742 if (sizeof(off_t) != 8) {
00743 fprintf(stderr,
00744 "\nFATAL: Compile time misconfiguration. off_t is not 64 bit.\n\n");
00745 exit(39);
00746 }
00747
00748 ret = libburner_setup(argc, argv);
00749 if (ret)
00750 exit(ret);
00751
00752 printf("Initializing libburnia-project.org ...\n");
00753 if (burn_initialize())
00754 printf("Done\n");
00755 else {
00756 printf("FAILED\n");
00757 fprintf(stderr,"\nFATAL: Failed to initialize.\n");
00758 exit(33);
00759 }
00760
00761
00762 burn_msgs_set_severities("NEVER", "SORRY", "libburner : ");
00763
00764
00765
00766 burn_set_signal_handling("libburner : ", NULL, 0x0);
00767
00768
00769 ret = libburner_aquire_drive(drive_adr, &driveno);
00770 if (ret<=0) {
00771 fprintf(stderr,"\nFATAL: Failed to aquire drive.\n");
00772 { ret = 34; goto finish_libburn; }
00773 }
00774 if (ret == 2)
00775 { ret = 0; goto release_drive; }
00776 if (do_blank) {
00777 if (do_blank > 100)
00778 ret = libburner_format(drive_list[driveno].drive);
00779 else
00780 ret = libburner_blank_disc(drive_list[driveno].drive,
00781 do_blank == 1);
00782 if (ret<=0)
00783 { ret = 36; goto release_drive; }
00784 }
00785 if (source_adr_count > 0) {
00786 ret = libburner_payload(drive_list[driveno].drive,
00787 source_adr, source_adr_count,
00788 do_multi, simulate_burn, all_tracks_type);
00789 if (ret<=0)
00790 { ret = 38; goto release_drive; }
00791 }
00792 ret = 0;
00793 release_drive:;
00794 if (drive_is_grabbed)
00795 burn_drive_release(drive_list[driveno].drive, 0);
00796
00797 finish_libburn:;
00798 if (burn_is_aborting(0) > 0) {
00799 burn_abort(4400, burn_abort_pacifier, "libburner : ");
00800 fprintf(stderr,"\nlibburner run aborted\n");
00801 exit(1);
00802 }
00803
00804
00805
00806 burn_finish();
00807 exit(ret);
00808 }
00809
00810
00811
00812
00813
00814
00815
00816
00817
00818
00819
00820
00821
00822
00823
00824
00825