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