#include "../libburn/libburn.h"
#include <stdio.h>
#include <ctype.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
Go to the source code of this file.
Functions | |
int | libburner_aquire_by_adr (char *drive_adr) |
If the persistent drive address is known, then this approach is much more un-obtrusive to the systemwide livestock of drives. | |
int | libburner_aquire_by_driveno (int *driveno) |
This method demonstrates how to use libburn without knowing a persistent drive address in advance. | |
int | libburner_aquire_drive (char *drive_adr, int *driveno) |
You need to aquire a drive before burning. | |
int | libburner_blank_disc (struct burn_drive *drive, int blank_fast) |
Makes a previously used CD-RW or unformatted DVD-RW ready for thorough re-usal. | |
int | libburner_format (struct burn_drive *drive) |
Formats unformatted DVD-RW to profile 0013h "Restricted Overwrite" which needs no blanking for re-use but is not capable of multi-session. | |
int | libburner_payload (struct burn_drive *drive, char source_adr[][4096], int source_adr_count, int multi, int simulate_burn, int all_tracks_type) |
Brings preformatted track images (ISO 9660, audio, . | |
int | libburner_setup (int argc, char **argv) |
Converts command line arguments into above setup parameters. | |
int | main (int argc, char **argv) |
Variables | |
static struct burn_drive_info * | drive_list |
Overview. | |
static unsigned int | drive_count |
If you start a long lasting operation with drive_count > 1 then you are not friendly to the users of other drives on those systems. | |
static int | drive_is_grabbed = 0 |
This variable indicates wether the drive is grabbed and must be finally released. | |
static int | current_profile = -1 |
A number and a text describing the type of media in aquired drive. | |
static char | current_profile_name [80] = {""} |
static char | drive_adr [BURN_DRIVE_ADR_LEN] = {""} |
The setup parameters of libburner. | |
static int | driveno = 0 |
static int | do_blank = 0 |
static char | source_adr [99][4096] |
static int | source_adr_count = 0 |
static int | do_multi = 0 |
static int | simulate_burn = 0 |
static int | all_tracks_type = BURN_MODE1 |
int libburner_aquire_by_adr | ( | char * | drive_adr | ) |
If the persistent drive address is known, then this approach is much more un-obtrusive to the systemwide livestock of drives.
Only the given drive device will be opened during this procedure.
Definition at line 139 of file libburner.c.
References BURN_DRIVE_ADR_LEN, burn_drive_convert_fs_adr(), burn_drive_scan_and_grab(), and drive_is_grabbed.
Referenced by libburner_aquire_drive().
00140 { 00141 int ret; 00142 char libburn_drive_adr[BURN_DRIVE_ADR_LEN]; 00143 00144 /* Some not-so-harmless drive addresses get blocked in this demo */ 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 /* This tries to resolve links or alternative device files */ 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 }
int libburner_aquire_by_driveno | ( | int * | driveno | ) |
This method demonstrates how to use libburn without knowing a persistent drive address in advance.
It has to make sure that after assessing the list of available drives, all unwanted drives get closed again. As long as they are open, no other libburn instance can see them. This is an intended locking feature. The application is responsible for giving up the locks by either burn_drive_release() (only after burn_drive_grab() !), burn_drive_info_forget(), burn_drive_info_free(), or burn_finish().
driveno | the index number in libburn's drive list. This will get set to 0 on success and will then be the drive index to use in the further dourse of processing. |
Definition at line 184 of file libburner.c.
References BURN_DRIVE_ADR_LEN, burn_drive_get_adr(), burn_drive_grab(), burn_drive_info_forget(), burn_drive_scan(), burn_drive_info::drive, drive_count, drive_is_grabbed, burn_drive_info::product, and burn_drive_info::vendor.
Referenced by libburner_aquire_drive().
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 Interactive programs may choose the drive number at this moment. 00200 00201 drive[0] to drive[drive_count-1] are struct burn_drive_info 00202 as defined in libburn/libburn.h . This structure is part of API 00203 and thus will strive for future compatibility on source level. 00204 Have a look at the info offered. 00205 Caution: do not take .location for drive address. Always use 00206 burn_drive_get_adr() or you might become incompatible 00207 in future. 00208 Note: bugs with struct burn_drive_info - if any - will not be 00209 easy to fix. Please report them but also strive for 00210 workarounds on application level. 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 On multi-drive systems save yourself from sysadmins' revenge. 00225 00226 Be aware that you hold reserved all available drives at this point. 00227 So either make your choice quick enough not to annoy other system 00228 users, or set free the drives for a while. 00229 00230 The tested way of setting free all drives is to shutdown the library 00231 and to restart when the choice has been made. The list of selectable 00232 drives should also hold persistent drive addresses as obtained 00233 above by burn_drive_get_adr(). By such an address one may use 00234 burn_drive_scan_and_grab() to finally aquire exactly one drive. 00235 00236 A not yet tested shortcut should be to call burn_drive_info_free() 00237 and to call either burn_drive_scan() or burn_drive_scan_and_grab() 00238 before accessing any drives again. 00239 00240 In both cases you have to be aware that the desired drive might get 00241 aquired in the meantime by another user resp. libburn process. 00242 */ 00243 00244 /* We already made our choice via command line. (default is 0) 00245 So we just have to keep our desired drive and drop all others. 00246 No other libburn instance will have a chance to steal our drive. 00247 */ 00248 if (*driveno < 0) { 00249 printf("Pseudo-drive \"-\" given : bus scanning done.\n"); 00250 return 2; /* the program will end after this */ 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; /* the program will end after this */ 00257 } 00258 00259 /* Drop all drives which we do not want to use */ 00260 for (i = 0; i < drive_count; i++) { 00261 if (i == *driveno) /* the one drive we want to keep */ 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 /* Make the one we want ready for blanking or burning */ 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 }
int libburner_aquire_drive | ( | char * | drive_adr, | |
int * | driveno | |||
) |
You need to aquire a drive before burning.
The API offers this as one compact call and alternatively as application controllable gestures of whitelisting, scanning for drives and finally grabbing one of them.
If you have a persistent address of the drive, then the compact call is to prefer because it only touches one drive. On modern Linux kernels, there should be no fatal disturbance of ongoing burns of other libburn instances with any of our approaches. We use open(O_EXCL) by default. On /dev/hdX it should cooperate with growisofs and some cdrecord variants. On /dev/sgN versus /dev/scdM expect it not to respect other programs.
Definition at line 117 of file libburner.c.
References burn_disc_get_profile(), current_profile, current_profile_name, burn_drive_info::drive, libburner_aquire_by_adr(), and libburner_aquire_by_driveno().
Referenced by main().
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 }
int libburner_blank_disc | ( | struct burn_drive * | drive, | |
int | blank_fast | |||
) |
Makes a previously used CD-RW or unformatted DVD-RW ready for thorough re-usal.
To our knowledge it is hardly possible to abort an ongoing blank operation because after start it is entirely handled by the drive. So expect signal handling to wait the normal blanking timespan until it can allow the process to end. External kill -9 will not help the drive.
Definition at line 287 of file libburner.c.
References BURN_DISC_APPENDABLE, BURN_DISC_BLANK, BURN_DISC_EMPTY, burn_disc_erasable(), burn_disc_erase(), BURN_DISC_FULL, burn_disc_get_status(), burn_drive_get_status(), BURN_DRIVE_IDLE, burn_is_aborting(), burn_set_signal_handling(), current_profile, burn_progress::sector, and burn_progress::sectors.
Referenced by main().
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 ; /* formatted DVD-RW will get blanked to sequential state */ 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 ; /* this is what libburner is willing to blank */ 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 /* Switch to asynchronous signal handling for the time of waiting */ 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) /* display 1 to 99 percent */ 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 /* Back to synchronous handling */ 00336 burn_set_signal_handling("libburner : ", NULL, 0); 00337 printf("Done\n"); 00338 return 1; 00339 }
int libburner_format | ( | struct burn_drive * | drive | ) |
Formats unformatted DVD-RW to profile 0013h "Restricted Overwrite" which needs no blanking for re-use but is not capable of multi-session.
Expect a behavior similar to blanking with unusual noises from the drive.
Formats unformatted BD-RE to default size. This will allocate some reserve space, test for bad blocks and make the media ready for writing. Expect a very long run time.
Formats unformatted blank BD-R to hold a default amount of spare blocks for eventual mishaps during writing. If BD-R get written without being formatted, then they get no such reserve and will burn at full speed.
Definition at line 354 of file libburner.c.
References BURN_DISC_BLANK, burn_disc_format(), burn_disc_get_formats(), burn_disc_get_profile(), burn_disc_get_status(), burn_drive_get_status(), BURN_DRIVE_IDLE, BURN_FORMAT_IS_UNFORMATTED, burn_is_aborting(), burn_set_signal_handling(), current_profile, current_profile_name, burn_progress::sector, and burn_progress::sectors.
Referenced by main().
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; /* does not really matter */ 00381 format_flag = 3<<1; /* format to default size, no quick */ 00382 } else if (current_profile == 0x14) { /* sequential DVD-RW */ 00383 size = 128 * 1024 * 1024; 00384 format_flag = 1; /* write initial 128 MiB */ 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) /* display 1 to 99 percent */ 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 }
int libburner_payload | ( | struct burn_drive * | drive, | |
char | source_adr[][4096], | |||
int | source_adr_count, | |||
int | multi, | |||
int | simulate_burn, | |||
int | all_tracks_type | |||
) |
Brings preformatted track images (ISO 9660, audio, .
..) onto media. To make sure a data image is fully readable on any Linux machine, this function adds 300 kiB of padding to the (usualy single) track. Audio tracks get padded to complete their last sector. A fifo of 4 MB is installed between each track and its data source. Each of the 4 MB buffers gets allocated automatically as soon as a track begins to be processed and it gets freed as soon as the track is done. The fifos do not wait for buffer fill but writing starts immediately.
In case of external signals expect abort handling of an ongoing burn to last up to a minute. Wait the normal burning timespan before any kill -9.
For simplicity, this function allows memory leaks in case of failure. In apps which do not abort immediately, one should clean up better.
Definition at line 434 of file libburner.c.
References BURN_AUDIO, burn_disc_add_session(), BURN_DISC_APPENDABLE, BURN_DISC_BLANK, burn_disc_create(), BURN_DISC_EMPTY, burn_disc_erasable(), burn_disc_free(), BURN_DISC_FULL, burn_disc_get_status(), burn_disc_write(), burn_drive_get_status(), BURN_DRIVE_IDLE, burn_drive_set_speed(), BURN_DRIVE_SPAWNING, burn_fd_source_new(), burn_fifo_inquire_status(), burn_fifo_source_new(), burn_is_aborting(), BURN_MODE1, BURN_POS_END, BURN_REASONS_LEN, burn_session_add_track(), burn_session_create(), burn_session_free(), burn_set_signal_handling(), burn_source_free(), BURN_SOURCE_OK, burn_track_create(), burn_track_define_data(), burn_track_free(), burn_track_set_source(), BURN_WRITE_NONE, burn_write_opts_auto_write_type(), burn_write_opts_free(), burn_write_opts_new(), burn_write_opts_set_multi(), burn_write_opts_set_perform_opc(), burn_write_opts_set_simulate(), burn_write_opts_set_underrun_proof(), current_profile, burn_progress::sector, burn_progress::sectors, and burn_progress::track.
Referenced by main().
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; /* ~ 4 MB fifo */ 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 /* a padding of 300 kiB helps to avoid the read-ahead bug */ 00455 padding = 300*1024; 00456 fifo_chunksize = 2048; 00457 fifo_chunks = 2048; /* 4 MB fifo */ 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 /* Open file descriptor to source of track data */ 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 /* Convert this filedescriptor into a burn_source object */ 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 /* Install a fifo object on top of that data source object */ 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 /* Use the fifo object as data source for the track */ 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 /* Give up local reference to the data burn_source object */ 00516 burn_source_free(data_src); 00517 00518 } /* trackno loop end */ 00519 00520 /* Evaluate drive and media */ 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 /* not with DVD+RW, formatted DVD-RW, DVD-RAM, BD-RE */ 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 }
int libburner_setup | ( | int | argc, | |
char ** | argv | |||
) |
Converts command line arguments into above setup parameters.
Definition at line 623 of file libburner.c.
References all_tracks_type, BURN_AUDIO, BURN_DRIVE_ADR_LEN, do_blank, do_multi, drive_adr, driveno, simulate_burn, source_adr, and source_adr_count.
Referenced by main().
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")) { /* obsoleted */ 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 }
int main | ( | int | argc, | |
char ** | argv | |||
) |
Note: driveno might change its value in this call
Definition at line 731 of file libburner.c.
References all_tracks_type, burn_abort(), burn_abort_pacifier(), burn_drive_release(), burn_finish(), burn_initialize(), burn_is_aborting(), burn_msgs_set_severities(), burn_set_signal_handling(), do_blank, do_multi, drive_adr, drive_is_grabbed, driveno, libburner_aquire_drive(), libburner_blank_disc(), libburner_format(), libburner_payload(), libburner_setup(), simulate_burn, source_adr, and source_adr_count.
00732 { 00733 int ret; 00734 00735 /* A warning to programmers who start their own projekt from here. */ 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 /* Print messages of severity SORRY or more directly to stderr */ 00756 burn_msgs_set_severities("NEVER", "SORRY", "libburner : "); 00757 00758 /* Activate the synchronous signal handler which eventually will try to 00759 properly shutdown drive and library on aborting events. */ 00760 burn_set_signal_handling("libburner : ", NULL, 0); 00761 00762 /** Note: driveno might change its value in this call */ 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 /* This app does not bother to know about exact scan state. 00798 Better to accept a memory leak here. We are done anyway. */ 00799 /* burn_drive_info_free(drive_list); */ 00800 burn_finish(); 00801 exit(ret); 00802 }
int all_tracks_type = BURN_MODE1 [static] |
Definition at line 618 of file libburner.c.
Referenced by libburner_setup(), and main().
int current_profile = -1 [static] |
A number and a text describing the type of media in aquired drive.
Definition at line 94 of file libburner.c.
Referenced by libburner_aquire_drive(), libburner_blank_disc(), libburner_format(), and libburner_payload().
char current_profile_name[80] = {""} [static] |
Definition at line 95 of file libburner.c.
Referenced by libburner_aquire_drive(), and libburner_format().
int do_blank = 0 [static] |
Definition at line 613 of file libburner.c.
Referenced by libburner_setup(), and main().
int do_multi = 0 [static] |
Definition at line 616 of file libburner.c.
Referenced by libburner_setup(), and main().
char drive_adr[BURN_DRIVE_ADR_LEN] = {""} [static] |
The setup parameters of libburner.
Definition at line 611 of file libburner.c.
Referenced by libburner_setup(), and main().
unsigned int drive_count [static] |
If you start a long lasting operation with drive_count > 1 then you are not friendly to the users of other drives on those systems.
Beware.
Definition at line 87 of file libburner.c.
Referenced by libburner_aquire_by_driveno().
int drive_is_grabbed = 0 [static] |
This variable indicates wether the drive is grabbed and must be finally released.
Definition at line 91 of file libburner.c.
Referenced by libburner_aquire_by_adr(), libburner_aquire_by_driveno(), and main().
struct burn_drive_info* drive_list [static] |
Overview.
libburner is a minimal demo application for the library libburn as provided on http://libburnia-project.org . It can list the available devices, can blank a CD-RW or DVD-RW, can format DVD-RW and BD, can burn to CD-R, CD-RW, DVD-R, DVD+R, DVD+R/DL, DVD+RW, DVD-RW, DVD-RAM, BD-R, BD-RE. Not supported yet: DVD-R/DL.
It's main purpose, nevertheless, is to show you how to use libburn and also to serve the libburnia team as reference application. libburner.c does indeed define the standard way how above three gestures can be implemented and stay upward compatible for a good while.
Before you can do anything, you have to initialize libburn by burn_initialize() and provide some signal and abort handling, e.g. by the builtin handler, by burn_set_signal_handling() as it is done in main() at the end of this file. Then you aquire a drive in an appropriate way conforming to the API. The two main approaches are shown here in application functions: libburner_aquire_by_adr() demonstrates usage as of cdrecord traditions libburner_aquire_by_driveno() demonstrates a scan-and-choose approach With that aquired drive you can blank a CD-RW or DVD-RW libburner_blank_disc() or you can format a DVD-RW to profile "Restricted Overwrite" (needed once) or an unused BD to default size with spare blocks libburner_format() With the aquired drive you can burn to CD, DVD, BD libburner_payload() When everything is done, main() releases the drive and shuts down libburn: burn_drive_release(); burn_finish()
FreeBSD does not work well with the convenient synchronous signal handler. So the waiting loops for blanking, formatting, and writing use the asynchronous mode of the libburn signal handler. It will not shutdown the library and abort the program, but rather tell the ongoing drive operation to stop as soon as possible. After the loops and at the end of the program there is a call to determine whether an abort happened: burn_is_aborting()
Applications must use 64 bit off_t. E.g. by defining define _LARGEFILE_SOURCE define _FILE_OFFSET_BITS 64 or take special precautions to interface with the library by 64 bit integers where libburn/libburn.h prescribes off_t. This program gets fed with appropriate settings externally by libburn's autotools generated build system. See this for the decisive API specs . libburn.h is The Original For simplicity i use global variables to represent the drives. Drives are systemwide global, so we do not give away much of good style. This list will hold the drives known to libburn. This might be all CD drives of the system and thus might impose severe impact on the system.
Definition at line 83 of file libburner.c.
int driveno = 0 [static] |
Definition at line 612 of file libburner.c.
Referenced by libburner_setup(), and main().
int simulate_burn = 0 [static] |
Definition at line 617 of file libburner.c.
Referenced by libburner_setup(), and main().
char source_adr[99][4096] [static] |
Definition at line 614 of file libburner.c.
Referenced by libburner_setup(), and main().
int source_adr_count = 0 [static] |
Definition at line 615 of file libburner.c.
Referenced by libburner_setup(), and main().