libburn-0.2.2/test/libburner.c

Go to the documentation of this file.
00001 
00002 /*  test/libburner.c , API illustration of burning a single data track to CD */
00003 /*  Copyright (C) 2005 - 2006 Thomas Schmitt <scdbackup@gmx.net> */
00004 /*  Provided under GPL, see also "License and copyright aspects" at file end */
00005 
00006 
00007 /**                               Overview 
00008   
00009   libburner is a minimal demo application for the library libburn as provided
00010   on  http://libburn.pykix.org . It can list the available devices, can
00011   blank a CD-RW and can burn to CD-R or CD-RW.
00012   It's main purpose, nevertheless, is to show you how to use libburn and also
00013   to serve the libburn team as reference application. libburner.c does indeed
00014   define the standard way how above three gestures can be implemented and
00015   stay upward compatible for a good while.
00016   
00017   Before you can do anything, you have to initialize libburn by
00018      burn_initialize()
00019   as it is done in main() at the end of this file. Then you aquire a
00020   drive in an appropriate way conforming to the API. The two main
00021   approaches are shown here in application functions:
00022      libburner_aquire_by_adr()     demonstrates usage as of cdrecord traditions
00023      libburner_aquire_by_driveno()      demonstrates a scan-and-choose approach
00024   With that aquired drive you can blank a CD-RW
00025      libburner_blank_disc()
00026   Between blanking and burning one eventually has to reload the drive status
00027      libburner_regrab()
00028   With the aquired drive you can burn to CD-R or blank CD-RW
00029      libburner_payload()
00030   When everything is done, main() releases the drive and shuts down libburn:
00031      burn_drive_release();
00032      burn_finish()
00033   
00034 */
00035 
00036 /* We shall prepare for times when more than 2 GB of data are to be handled.
00037    This gives POSIX-ly 64 bit off_t */
00038 #ifndef _LARGEFILE_SOURCE
00039 #define _LARGEFILE_SOURCE 1
00040 #endif
00041 #ifndef _FILE_OFFSET_BITS
00042 #define _FILE_OFFSET_BITS 64
00043 #endif
00044 
00045 /** See this for the decisive API specs . libburn.h is The Original */
00046 #include <libburn/libburn.h>
00047 
00048 /* libburn is intended for Linux systems with kernel 2.4 or 2.6 for now */
00049 #include <stdio.h>
00050 #include <ctype.h>
00051 #include <sys/types.h>
00052 #include <unistd.h>
00053 #include <string.h>
00054 #include <stdlib.h>
00055 #include <time.h>
00056 #include <errno.h>
00057 
00058 
00059 /** For simplicity i use global variables to represent the drives.
00060     Drives are systemwide global, so we do not give away much of good style.
00061 */
00062 
00063 /** This list will hold the drives known to libburn. This might be all CD
00064     drives of the system and thus might impose severe impact on the system.
00065 */
00066 static struct burn_drive_info *drive_list;
00067 
00068 /** If you start a long lasting operation with drive_count > 1 then you are
00069     not friendly to the users of other drives on those systems. Beware. */
00070 static unsigned int drive_count;
00071 
00072 /** This variable indicates wether the drive is grabbed and must be
00073     finally released */
00074 static int drive_is_grabbed = 0;
00075 
00076 
00077 /** Here you may enable simulated burn by default. This does not apply to
00078     blanking. Anyway, some CD recorders obey the request to simulate, some do
00079     not. Explicit options are:  --burn_for_real  and  --try_to_simulate
00080 */
00081 static int simulate_burn = 0;
00082 
00083 
00084 /* Some in-advance definitions to allow a more comprehensive ordering
00085    of the functions and their explanations in here */
00086 int libburner_aquire_by_adr(char *drive_adr);
00087 int libburner_aquire_by_driveno(int *drive_no);
00088 
00089 
00090 /* ------------------------------- API gestures ---------------------------- */
00091 
00092 /** You need to aquire a drive before burning. The API offers this as one
00093     compact call and alternatively as application controllable gestures of
00094     whitelisting, scanning for drives and finally grabbing one of them.
00095 
00096     If you have a persistent address of the drive, then the compact call is
00097     to prefer because it only touches one drive. On modern Linux kernels,
00098     there should be no fatal disturbance of ongoing burns of other libburn
00099     instances with any of our approaches. We use open(O_EXCL) by default.
00100     On /dev/hdX it should cooperate with growisofs and some cdrecord variants.
00101     On /dev/sgN versus /dev/scdM expect it not to respect other programs.
00102 */
00103 int libburner_aquire_drive(char *drive_adr, int *driveno)
00104 {
00105     int ret;
00106 
00107     if(drive_adr != NULL && drive_adr[0] != 0)
00108         ret = libburner_aquire_by_adr(drive_adr);
00109     else
00110         ret = libburner_aquire_by_driveno(driveno);
00111     return ret;
00112 }
00113 
00114 
00115 /** If the persistent drive address is known, then this approach is much
00116     more un-obtrusive to the systemwide livestock of drives. Only the
00117     given drive device will be opened during this procedure.
00118 */
00119 int libburner_aquire_by_adr(char *drive_adr)
00120 {
00121     int ret;
00122     
00123     printf("Aquiring drive '%s' ...\n",drive_adr);
00124     ret = burn_drive_scan_and_grab(&drive_list,drive_adr,1);
00125     if (ret <= 0) {
00126         fprintf(stderr,"FAILURE with persistent drive address  '%s'\n",
00127             drive_adr);
00128         if (strncmp(drive_adr,"/dev/sg",7) != 0 &&
00129             strncmp(drive_adr,"/dev/hd",7) != 0)
00130             fprintf(stderr,"\nHINT: Consider addresses like  '/dev/hdc'  or  '/dev/sg0'\n");
00131     } else {
00132         printf("Done\n");
00133         drive_is_grabbed = 1;
00134     }
00135     return ret;
00136 }
00137 
00138 
00139 /** This method demonstrates how to use libburn without knowing a persistent
00140     drive address in advance. It has to make sure that after assessing the list
00141     of available drives, all unwanted drives get closed again. As long as they
00142     are open, no other libburn instance can see them. This is an intended
00143     locking feature. The application is responsible for giving up the locks
00144     by either burn_drive_release() (only after burn_drive_grab() !),
00145     burn_drive_info_forget(), burn_drive_info_free(), or burn_finish().
00146     @param driveno the index number in libburn's drive list. This will get
00147                    set to 0 on success and will then be the drive index to
00148                    use in the further dourse of processing.
00149     @return 1 success , <= 0 failure
00150 */
00151 int libburner_aquire_by_driveno(int *driveno)
00152 {
00153     char adr[BURN_DRIVE_ADR_LEN];
00154     int ret, i;
00155 
00156     printf("Beginning to scan for devices ...\n");
00157     while (!burn_drive_scan(&drive_list, &drive_count))
00158         usleep(1002);
00159     if (drive_count <= 0 && *driveno >= 0) {
00160         printf("FAILED (no drives found)\n");
00161         return 0;
00162     }
00163     printf("Done\n");
00164 
00165     /*
00166     Interactive programs may choose the drive number at this moment.
00167 
00168     drive[0] to drive[drive_count-1] are struct burn_drive_info
00169     as defined in  libburn/libburn.h  . This structure is part of API
00170     and thus will strive for future compatibility on source level.
00171     Have a look at the info offered.
00172     Caution: do not take .location for drive address. Always use
00173         burn_drive_get_adr() or you might become incompatible
00174         in future.
00175     Note: bugs with struct burn_drive_info - if any - will not be
00176         easy to fix. Please report them but also strive for
00177         workarounds on application level.
00178     */
00179     printf("\nOverview of accessible drives (%d found) :\n",
00180         drive_count);
00181     printf("-----------------------------------------------------------------------------\n");
00182     for (i = 0; i < drive_count; i++) {
00183         if (burn_drive_get_adr(&(drive_list[i]), adr) <=0)
00184             strcpy(adr, "-get_adr_failed-");
00185         printf("%d  --drive '%s'  :  '%s'  '%s'\n",
00186             i,adr,drive_list[i].vendor,drive_list[i].product);
00187     }
00188     printf("-----------------------------------------------------------------------------\n\n");
00189 
00190 
00191     /*
00192     On multi-drive systems save yourself from sysadmins' revenge.
00193 
00194     Be aware that you hold reserved all available drives at this point.
00195     So either make your choice quick enough not to annoy other system
00196     users, or set free the drives for a while.
00197 
00198     The tested way of setting free all drives is to shutdown the library
00199     and to restart when the choice has been made. The list of selectable
00200     drives should also hold persistent drive addresses as obtained
00201     above by burn_drive_get_adr(). By such an address one may use
00202     burn_drive_scan_and_grab() to finally aquire exactly one drive.
00203 
00204     A not yet tested shortcut should be to call burn_drive_info_free()
00205     and to call either burn_drive_scan() or burn_drive_scan_and_grab()
00206     before accessing any drives again.
00207 
00208     In both cases you have to be aware that the desired drive might get
00209     aquired in the meantime by another user resp. libburn process.
00210     */
00211 
00212     /* We already made our choice via command line. (default is 0)
00213        So we just have to keep our desired drive and drop all others.
00214        No other libburn instance will have a chance to steal our drive.
00215      */
00216     if (*driveno < 0) {
00217         printf("Pseudo-drive \"-\" given : bus scanning done.\n");
00218         return 2; /* the program will end after this */
00219     }
00220     if (drive_count <= *driveno) {
00221         fprintf(stderr,
00222             "Found only %d drives. Number %d not available.\n",
00223             drive_count, *driveno);
00224         return 0; /* the program will end after this */
00225     }
00226 
00227     /* Drop all drives which we do not want to use */
00228     for (i = 0; i < drive_count; i++) {
00229         if (i == *driveno) /* the one drive we want to keep */
00230     continue;
00231         ret = burn_drive_info_forget(&(drive_list[i]),0);
00232         if (ret != 1)
00233             fprintf(stderr, "Cannot drop drive %d. Please report \"ret=%d\" to libburn-hackers@pykix.org\n",
00234                 i, ret);
00235         else
00236             printf("Dropped unwanted drive %d\n",i);
00237     }
00238     /* Make the one we want ready for blanking or burning */
00239     ret= burn_drive_grab(drive_list[*driveno].drive, 1);
00240     if (ret != 1)
00241         return 0;
00242     drive_is_grabbed = 1;
00243     return 1;
00244 }
00245 
00246 
00247 /** Makes a previously used CD-RW ready for thorough re-usal.
00248 
00249     To our knowledge it is hardly possible to abort an ongoing blank operation
00250     because after start it is entirely handled by the drive.
00251     So expect a blank run to survive the end of the blanking process and be
00252     patient for the usual timespan of a normal blank run. Only after that
00253     time has surely elapsed, only then you should start any rescue attempts
00254     with the drive. If necessary at all.
00255 */
00256 int libburner_blank_disc(struct burn_drive *drive, int blank_fast)
00257 {
00258     enum burn_disc_status disc_state;
00259     struct burn_progress progress;
00260 
00261     while (burn_drive_get_status(drive, NULL))
00262         usleep(1001);
00263 
00264     while ((disc_state = burn_disc_get_status(drive)) == BURN_DISC_UNREADY)
00265         usleep(1001);
00266     printf(
00267         "Drive media status:  %d  (see  libburn/libburn.h  BURN_DISC_*)\n",
00268         disc_state);
00269     if (disc_state == BURN_DISC_BLANK) {
00270         fprintf(stderr,
00271           "IDLE: Blank CD media detected. Will leave it untouched\n");
00272         return 2;
00273     } else if (disc_state == BURN_DISC_FULL ||
00274            disc_state == BURN_DISC_APPENDABLE) {
00275         ; /* this is what libburn is willing to blank */
00276     } else if (disc_state == BURN_DISC_EMPTY) {
00277         fprintf(stderr,"FATAL: No media detected in drive\n");
00278         return 0;
00279     } else {
00280         fprintf(stderr,
00281             "FATAL: Cannot recognize drive and media state\n");
00282         return 0;
00283     }
00284     if(!burn_disc_erasable(drive)) {
00285         fprintf(stderr,
00286             "FATAL : Media is not of erasable type\n");
00287         return 0;
00288     }
00289     printf(
00290           "Beginning to %s-blank CD media.\n", (blank_fast?"fast":"full"));
00291     printf(
00292           "Expect some garbage sector numbers and some zeros at first.\n");
00293     burn_disc_erase(drive, blank_fast);
00294     while (burn_drive_get_status(drive, &progress)) {
00295         printf("Blanking sector  %d\n", progress.sector);
00296         sleep(1);
00297     }
00298     printf("Done\n");
00299     return 1;
00300 }
00301 
00302 
00303 /** This gesture is necessary to get the drive info after blanking.
00304     It opens a small gap for losing the drive to another libburn instance.
00305     We will work on closing this gap.
00306 */
00307 int libburner_regrab(struct burn_drive *drive) {
00308     int ret;
00309 
00310     printf("Releasing and regrabbing drive ...\n");
00311     if (drive_is_grabbed)
00312         burn_drive_release(drive, 0);
00313     drive_is_grabbed = 0;
00314     ret = burn_drive_grab(drive, 0);
00315     if (ret != 0) {
00316         drive_is_grabbed = 1;
00317         printf("Done\n");
00318     } else
00319         printf("FAILED\n");
00320     return !!ret;
00321 }
00322 
00323 
00324 /** Brings the preformatted image (ISO 9660, afio, ext2, whatever) onto media.
00325 
00326     To make sure your image is fully readable on any Linux machine, this
00327     function adds 300 kB of padding to the track.
00328 
00329     Without a signal handler it is quite dangerous to abort the process
00330     while this function is active. See cdrskin/cdrskin.c and its usage
00331     of cdrskin/cleanup.[ch] for an example of application provided
00332     abort handling. It must cope with 2 of 3 threads reporting for
00333     being handled.
00334 
00335     Without signal handler have ready a command line 
00336        cdrecord dev=... -reset
00337     with a dev= previously inquired by cdrecord [dev=ATA] -scanbus 
00338     in order to get your drive out of shock state after raw abort.
00339     Thanks to Joerg Schilling for helping out unquestioned. :) 
00340 
00341     In general, libburn is less prone to system problems than cdrecord,
00342     i believe. But cdrecord had long years of time to complete itself.
00343     We are still practicing. Help us with that. :))
00344 */
00345 int libburner_payload(struct burn_drive *drive, const char *source_adr,
00346              off_t size)
00347 {
00348     struct burn_source *data_src;
00349     struct burn_disc *target_disc;
00350     struct burn_session *session;
00351     struct burn_write_opts *burn_options;
00352     enum burn_disc_status disc_state;
00353     struct burn_track *track;
00354     struct burn_progress progress;
00355     time_t start_time;
00356     int last_sector = 0;
00357 
00358     target_disc = burn_disc_create();
00359     session = burn_session_create();
00360     burn_disc_add_session(target_disc, session, BURN_POS_END);
00361     track = burn_track_create();
00362 
00363     /* a padding of 300 kB is helpful to avoid the read-ahead bug */
00364     burn_track_define_data(track, 0, 300*1024, 1, BURN_MODE1);
00365 
00366     if (source_adr[0] == '-' && source_adr[1] == 0) {
00367         data_src = burn_fd_source_new(0, -1, size);
00368         printf("Note: using standard input as source with %.f bytes\n",
00369             (double) size);
00370     } else
00371         data_src = burn_file_source_new(source_adr, NULL);
00372     if (data_src == NULL) {
00373         fprintf(stderr,
00374                "FATAL: Could not open data source '%s'.\n",source_adr);
00375         if(errno!=0)
00376             fprintf(stderr,"(Most recent system error: %s )\n",
00377                 strerror(errno));
00378         return 0;
00379     }
00380 
00381     if (burn_track_set_source(track, data_src) != BURN_SOURCE_OK) {
00382         printf("FATAL: Cannot attach source object to track object\n");
00383         return 0;
00384     }
00385     burn_session_add_track(session, track, BURN_POS_END);
00386     burn_source_free(data_src);
00387 
00388     while (burn_drive_get_status(drive, NULL))
00389         usleep(1001);
00390 
00391     /* Evaluate drive and media */
00392     while ((disc_state = burn_disc_get_status(drive)) == BURN_DISC_UNREADY)
00393         usleep(1001);
00394     if (disc_state != BURN_DISC_BLANK) {
00395         if (disc_state == BURN_DISC_FULL ||
00396             disc_state == BURN_DISC_APPENDABLE) {
00397             fprintf(stderr,
00398                    "FATAL: Media with data detected. Need blank media.\n");
00399             if (burn_disc_erasable(drive))
00400                 fprintf(stderr, "HINT: Try --blank_fast\n\n");
00401         } else if (disc_state == BURN_DISC_EMPTY) 
00402             fprintf(stderr,"FATAL: No media detected in drive\n");
00403         else
00404             fprintf(stderr,
00405                 "FATAL: Cannot recognize drive and media state\n");
00406         return 0;
00407     }
00408 
00409     burn_options = burn_write_opts_new(drive);
00410     burn_write_opts_set_perform_opc(burn_options, 0);
00411 
00412 #ifdef Libburner_raw_mode_which_i_do_not_likE
00413     /* This yields higher CD capacity but hampers my IDE controller
00414        with burning on one drive and reading on another simultaneously.
00415        My burner does not obey the order --try_to_simulate in this mode.
00416         */
00417     burn_write_opts_set_write_type(burn_options,
00418                        BURN_WRITE_RAW, BURN_BLOCK_RAW96R);
00419 #else
00420 
00421     /* This is by what cdrskin competes with cdrecord -sao which
00422        i understand is the mode preferrably advised by Joerg Schilling */
00423     burn_write_opts_set_write_type(burn_options,
00424                        BURN_WRITE_SAO, BURN_BLOCK_SAO);
00425 
00426 #endif
00427     if(simulate_burn)
00428         printf("\n*** Will TRY to SIMULATE burning ***\n\n");
00429     burn_write_opts_set_simulate(burn_options, simulate_burn);
00430     burn_structure_print_disc(target_disc);
00431     burn_drive_set_speed(drive, 0, 0);
00432     burn_write_opts_set_underrun_proof(burn_options, 1);
00433 
00434     printf("Burning starts. With e.g. 4x media expect up to a minute of zero progress.\n");
00435     start_time = time(0);
00436     burn_disc_write(burn_options, target_disc);
00437 
00438     burn_write_opts_free(burn_options);
00439     while (burn_drive_get_status(drive, NULL) == BURN_DRIVE_SPAWNING)
00440         usleep(1002);
00441     while (burn_drive_get_status(drive, &progress)) {
00442         if( progress.sectors <= 0 || progress.sector == last_sector)
00443             printf(
00444                  "Thank you for being patient since %d seconds.\n",
00445                  (int) (time(0) - start_time));
00446         else
00447             printf("Burning sector %d of %d\n",
00448                 progress.sector, progress.sectors);
00449         last_sector = progress.sector;
00450         sleep(1);
00451     }
00452     printf("\n");
00453     burn_track_free(track);
00454     burn_session_free(session);
00455     burn_disc_free(target_disc);
00456     if(simulate_burn)
00457         printf("\n*** Did TRY to SIMULATE burning ***\n\n");
00458     return 0;
00459 }
00460 
00461 
00462 /** Converts command line arguments into a few program parameters.
00463     drive_adr[] must provide at least BURN_DRIVE_ADR_LEN bytes.
00464     source_adr[] must provide at least 4096 bytes.
00465 */
00466 int libburner_setup(int argc, char **argv, char drive_adr[], int *driveno,
00467                    int *do_blank, char source_adr[], off_t *size)
00468 {
00469     int i, insuffient_parameters = 0;
00470     int print_help = 0;
00471 
00472     drive_adr[0] = 0;
00473     *driveno = 0;
00474     *do_blank = 0;
00475     source_adr[0] = 0;
00476     *size = 650*1024*1024;
00477 
00478     for (i = 1; i < argc; ++i) {
00479         if (!strcmp(argv[i], "--blank_fast")) {
00480             *do_blank = 1;
00481 
00482         } else if (!strcmp(argv[i], "--blank_full")) {
00483             *do_blank = 2;
00484 
00485         } else if (!strcmp(argv[i], "--burn_for_real")) {
00486             simulate_burn = 0;
00487 
00488         } else if (!strcmp(argv[i], "--drive")) {
00489             ++i;
00490             if (i >= argc) {
00491                 fprintf(stderr,"--drive requires an argument\n");
00492                 return 1;
00493             } else if (strcmp(argv[i], "-") == 0) {
00494                 drive_adr[0] = 0;
00495                 *driveno = -1;
00496             } else if (isdigit(argv[i][0])) {
00497                 drive_adr[0] = 0;
00498                 *driveno = atoi(argv[i]);
00499             } else {
00500                 if(strlen(argv[i]) >= BURN_DRIVE_ADR_LEN) {
00501                     fprintf(stderr,"--drive address too long (max. %d)\n",
00502                             BURN_DRIVE_ADR_LEN-1);
00503                     return 2;
00504                 }
00505                 strcpy(drive_adr, argv[i]);
00506             }
00507         } else if (!strcmp(argv[i], "--stdin_size")) {
00508             ++i;
00509             if (i >= argc) {
00510                 fprintf(stderr,"--stdin_size requires an argument\n");
00511                 return 3;
00512             } else
00513                 *size = atoi(argv[i]);
00514             if (*size < 600*1024) /* seems to be minimum readable track size */
00515                 *size = 600*1024;
00516         } else if (!strcmp(argv[i], "--try_to_simulate")) {
00517             simulate_burn = 1;
00518 
00519         } else if (!strcmp(argv[i], "--verbose")) {
00520             ++i;
00521             if (i >= argc) {
00522                 fprintf(stderr,"--verbose requires an argument\n");
00523                 return 4;
00524             } else
00525                 burn_set_verbosity(atoi(argv[i]));
00526         } else if (!strcmp(argv[i], "--help")) {
00527             print_help = 1;
00528 
00529         } else {
00530             if(strlen(argv[i]) >= 4096) {
00531                 fprintf(stderr, "Source address too long (max. %d)\n", 4096-1);
00532                 return 5;
00533             }
00534             strcpy(source_adr, argv[i]);
00535         }
00536     }
00537     insuffient_parameters = 1;
00538     if (*driveno < 0)
00539         insuffient_parameters = 0;
00540     if (source_adr[0] != 0)
00541         insuffient_parameters = 0; 
00542     if (*do_blank)
00543         insuffient_parameters = 0;
00544     if (print_help || insuffient_parameters ) {
00545         printf("Usage: %s\n", argv[0]);
00546         printf("       [--drive <address>|<driveno>|\"-\"]\n");
00547         printf("       [--verbose <level>] [--blank_fast|--blank_full]\n");
00548         printf("       [--burn_for_real|--try_to_simulate] [--stdin_size <bytes>]\n");
00549         printf("       [<imagefile>|\"-\"]\n");
00550         printf("Examples\n");
00551         printf("A bus scan (needs rw-permissions to see a drive):\n");
00552         printf("  %s --drive -\n",argv[0]);
00553         printf("Burn a file to drive chosen by number:\n");
00554         printf("  %s --drive 0 --burn_for_real my_image_file\n",
00555             argv[0]);
00556         printf("Burn a file to drive chosen by persistent address:\n");
00557         printf("  %s --drive /dev/hdc --burn_for_real my_image_file\n", argv[0]);
00558         printf("Blank a used CD-RW (is combinable with burning in one run):\n");
00559         printf("  %s --drive 0 --blank_fast\n",argv[0]);
00560         printf("Burn a compressed afio archive on-the-fly, pad up to 700 MB:\n");
00561         printf("  ( cd my_directory ; find . -print | afio -oZ - ) | \\\n");
00562         printf("  %s --drive /dev/hdc --burn_for_real --stdin_size 734003200  -\n", argv[0]);
00563         printf("To be read from *not mounted* CD via:\n");
00564         printf("   afio -tvZ /dev/hdc\n");
00565         printf("Program tar would need a clean EOF which our padded CD cannot deliver.\n");
00566         if (insuffient_parameters)
00567             return 6;
00568     }
00569     return 0;
00570 }
00571 
00572 
00573 int main(int argc, char **argv)
00574 {
00575     int driveno, ret, do_blank;
00576     char source_adr[4096], drive_adr[BURN_DRIVE_ADR_LEN];
00577     off_t stdin_size;
00578 
00579     ret = libburner_setup(argc, argv, drive_adr, &driveno, &do_blank, 
00580                source_adr, &stdin_size);
00581     if (ret)
00582         exit(ret);
00583 
00584     printf("Initializing library ...\n");
00585     if (burn_initialize())
00586         printf("Done\n");
00587     else {
00588         printf("FAILED\n");
00589         fprintf(stderr,"\nFATAL: Failed to initialize libburn.\n");
00590         exit(33);
00591     }
00592 
00593     /** Note: driveno might change its value in this call */
00594     ret = libburner_aquire_drive(drive_adr, &driveno);
00595     if (ret<=0) {
00596         fprintf(stderr,"\nFATAL: Failed to aquire drive.\n");
00597         { ret = 34; goto finish_libburn; }
00598     }
00599     if (ret == 2)
00600         { ret = 0; goto release_drive; }
00601     if (do_blank) {
00602         ret = libburner_blank_disc(drive_list[driveno].drive,
00603                       do_blank == 1);
00604         if (ret<=0)
00605             { ret = 36; goto release_drive; }
00606         if (ret != 2 && source_adr[0] != 0)
00607             ret = libburner_regrab(drive_list[driveno].drive);
00608         if (ret<=0) {
00609             fprintf(stderr,
00610             "FATAL: Cannot release and grab again drive after blanking\n");
00611             { ret = 37; goto finish_libburn; }
00612         }
00613     }
00614     if (source_adr[0] != 0) {
00615         ret = libburner_payload(drive_list[driveno].drive, source_adr,
00616                  stdin_size);
00617         if (ret<=0)
00618             { ret = 38; goto release_drive; }
00619     }
00620     ret = 0;
00621 release_drive:;
00622     if (drive_is_grabbed)
00623         burn_drive_release(drive_list[driveno].drive, 0);
00624 
00625 finish_libburn:;
00626     /* This app does not bother to know about exact scan state. 
00627        Better to accept a memory leak here. We are done anyway. */
00628     /* burn_drive_info_free(drive_list); */
00629 
00630     burn_finish();
00631     return ret;
00632 }
00633 
00634 
00635 /*  License and copyright aspects:
00636 
00637 This all is provided under GPL.
00638 Read. Try. Think. Play. Write yourself some code. Be free of my copyright.
00639 
00640 Be also invited to study the code of cdrskin/cdrskin.c et al.
00641 
00642 
00643 Clarification in my name and in the name of Mario Danic, copyright holder
00644 on toplevel of libburn. To be fully in effect after the remaining other
00645 copyrighted code has been replaced by ours and by copyright-free contributions
00646 of our friends:
00647 
00648 We, the copyright holders, agree on the interpretation that
00649 dynamical linking of our libraries constitutes "use of" and
00650 not "derivation from" our work in the sense of GPL, provided
00651 those libraries are compiled from our unaltered code.
00652 
00653 Thus you may link our libraries dynamically with applications
00654 which are not under GPL. You may distribute our libraries and
00655 application tools in binary form, if you fulfill the usual
00656 condition of GPL to offer a copy of the source code -altered
00657 or unaltered- under GPL.
00658 
00659 We ask you politely to use our work in open source spirit
00660 and with the due reference to the entire open source community.
00661 
00662 If there should really arise the case where above clarification
00663 does not suffice to fulfill a clear and neat request in open source
00664 spirit that would otherwise be declined for mere formal reasons,
00665 only in that case we will duely consider to issue a special license
00666 covering only that special case.
00667 It is the open source idea of responsible freedom which will be
00668 decisive and you will have to prove that you exhausted all own
00669 means to qualify for GPL.
00670 
00671 For now we are firmly committed to maintain one single license: GPL.
00672 
00673 History:
00674 libburner is a compilation of my own contributions to test/burniso.c and
00675 fresh code which replaced the remaining parts under copyright of
00676 Derek Foreman.
00677 My respect and my thanks to Derek for providing me a start back in 2005.
00678 
00679 */
00680 

Generated on Fri Sep 29 11:57:28 2006 for libburn by  doxygen 1.4.7