libburn  1.3.8
Functions | Variables
libburner.c File Reference
#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. More...
 
int libburner_aquire_by_driveno (int *driveno)
 This method demonstrates how to use libburn without knowing a persistent drive address in advance. More...
 
int libburner_aquire_drive (char *drive_adr, int *driveno)
 You need to aquire a drive before burning. More...
 
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. More...
 
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. More...
 
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. More...
 
int libburner_setup (int argc, char **argv)
 Converts command line arguments into above setup parameters. More...
 
int main (int argc, char **argv)
 

Variables

static struct burn_drive_infodrive_list
 Overview. More...
 
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. More...
 
static int drive_is_grabbed = 0
 This variable indicates wether the drive is grabbed and must be finally released. More...
 
static int current_profile = -1
 A number and a text describing the type of media in aquired drive. More...
 
static char current_profile_name [80] = {""}
 
static char drive_adr [BURN_DRIVE_ADR_LEN] = {""}
 The setup parameters of libburner. More...
 
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
 

Function Documentation

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 145 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().

146 {
147  int ret;
148  char libburn_drive_adr[BURN_DRIVE_ADR_LEN];
149 
150  /* Some not-so-harmless drive addresses get blocked in this demo */
151  if (strncmp(drive_adr, "stdio:/dev/fd/", 14) == 0 ||
152  strcmp(drive_adr, "stdio:-") == 0) {
153  fprintf(stderr, "Will not work with pseudo-drive '%s'\n",
154  drive_adr);
155  return 0;
156  }
157 
158  /* This tries to resolve links or alternative device files */
159  ret = burn_drive_convert_fs_adr(drive_adr, libburn_drive_adr);
160  if (ret<=0) {
161  fprintf(stderr, "Address does not lead to a CD burner: '%s'\n",
162  drive_adr);
163  return 0;
164  }
165  fprintf(stderr,"Aquiring drive '%s' ...\n", libburn_drive_adr);
166  ret = burn_drive_scan_and_grab(&drive_list, libburn_drive_adr, 1);
167  if (ret <= 0) {
168  fprintf(stderr,"FAILURE with persistent drive address '%s'\n",
169  libburn_drive_adr);
170  } else {
171  fprintf(stderr,"Done\n");
172  drive_is_grabbed = 1;
173  }
174  return ret;
175 }
#define BURN_DRIVE_ADR_LEN
Maximum length+1 to expect with a drive device file address string.
Definition: libburn.h:1037
static int drive_is_grabbed
This variable indicates wether the drive is grabbed and must be finally released. ...
Definition: libburner.c:97
static char drive_adr[BURN_DRIVE_ADR_LEN]
The setup parameters of libburner.
Definition: libburner.c:617
int burn_drive_convert_fs_adr(char *path, char adr[])
Try to convert a given existing filesystem address into a drive device file address.
int burn_drive_scan_and_grab(struct burn_drive_info *drive_infos[], char *adr, int load)
Aquire a drive with known device file address.
static struct burn_drive_info * drive_list
Overview.
Definition: libburner.c:89
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().

Parameters
drivenothe 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.
Returns
1 success , <= 0 failure

Definition at line 190 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().

191 {
192  char adr[BURN_DRIVE_ADR_LEN];
193  int ret, i;
194 
195  printf("Beginning to scan for devices ...\n");
197  usleep(100002);
198  if (drive_count <= 0 && *driveno >= 0) {
199  printf("FAILED (no drives found)\n");
200  return 0;
201  }
202  printf("Done\n");
203 
204  /*
205  Interactive programs may choose the drive number at this moment.
206 
207  drive[0] to drive[drive_count-1] are struct burn_drive_info
208  as defined in libburn/libburn.h . This structure is part of API
209  and thus will strive for future compatibility on source level.
210  Have a look at the info offered.
211  Caution: do not take .location for drive address. Always use
212  burn_drive_get_adr() or you might become incompatible
213  in future.
214  Note: bugs with struct burn_drive_info - if any - will not be
215  easy to fix. Please report them but also strive for
216  workarounds on application level.
217  */
218  printf("\nOverview of accessible drives (%d found) :\n",
219  drive_count);
220  printf("-----------------------------------------------------------------------------\n");
221  for (i = 0; i < (int) drive_count; i++) {
222  if (burn_drive_get_adr(&(drive_list[i]), adr) <=0)
223  strcpy(adr, "-get_adr_failed-");
224  printf("%d --drive '%s' : '%s' '%s'\n",
225  i,adr,drive_list[i].vendor,drive_list[i].product);
226  }
227  printf("-----------------------------------------------------------------------------\n\n");
228 
229  /*
230  On multi-drive systems save yourself from sysadmins' revenge.
231 
232  Be aware that you hold reserved all available drives at this point.
233  So either make your choice quick enough not to annoy other system
234  users, or set free the drives for a while.
235 
236  The tested way of setting free all drives is to shutdown the library
237  and to restart when the choice has been made. The list of selectable
238  drives should also hold persistent drive addresses as obtained
239  above by burn_drive_get_adr(). By such an address one may use
240  burn_drive_scan_and_grab() to finally aquire exactly one drive.
241 
242  A not yet tested shortcut should be to call burn_drive_info_free()
243  and to call either burn_drive_scan() or burn_drive_scan_and_grab()
244  before accessing any drives again.
245 
246  In both cases you have to be aware that the desired drive might get
247  aquired in the meantime by another user resp. libburn process.
248  */
249 
250  /* We already made our choice via command line. (default is 0)
251  So we just have to keep our desired drive and drop all others.
252  No other libburn instance will have a chance to steal our drive.
253  */
254  if (*driveno < 0) {
255  printf("Pseudo-drive \"-\" given : bus scanning done.\n");
256  return 2; /* the program will end after this */
257  }
258  if ((int) drive_count <= *driveno) {
259  fprintf(stderr,
260  "Found only %d drives. Number %d not available.\n",
261  drive_count, *driveno);
262  return 0; /* the program will end after this */
263  }
264 
265  /* Drop all drives which we do not want to use */
266  for (i = 0; i < (int) drive_count; i++) {
267  if (i == *driveno) /* the one drive we want to keep */
268  continue;
269  ret = burn_drive_info_forget(&(drive_list[i]),0);
270  if (ret != 1)
271  fprintf(stderr, "Cannot drop drive %d. Please report \"ret=%d\" to libburn-hackers@pykix.org\n",
272  i, ret);
273  else
274  printf("Dropped unwanted drive %d\n",i);
275  }
276  /* Make the one we want ready for blanking or burning */
277  ret= burn_drive_grab(drive_list[*driveno].drive, 1);
278  if (ret != 1)
279  return 0;
280  drive_is_grabbed = 1;
281  return 1;
282 }
#define BURN_DRIVE_ADR_LEN
Maximum length+1 to expect with a drive device file address string.
Definition: libburn.h:1037
static int drive_is_grabbed
This variable indicates wether the drive is grabbed and must be finally released. ...
Definition: libburner.c:97
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 ...
Definition: libburner.c:93
int burn_drive_scan(struct burn_drive_info *drive_infos[], unsigned int *n_drives)
Scan for drives.
int burn_drive_info_forget(struct burn_drive_info *drive_info, int force)
Release memory about a single drive and any exclusive lock on it.
static struct burn_drive_info * drive_list
Overview.
Definition: libburner.c:89
static int driveno
Definition: libburner.c:618
int burn_drive_get_adr(struct burn_drive_info *drive_info, char adr[])
Inquire the device file address of a drive via a given drive_info object.
int burn_drive_grab(struct burn_drive *drive, int load)
Grab a drive.
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 123 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().

124 {
125  int ret;
126 
127  if(drive_adr != NULL && drive_adr[0] != 0)
129  else
131  if (ret <= 0 || *driveno <= 0)
132  return ret;
135  if (current_profile_name[0])
136  printf("Detected media type: %s\n", current_profile_name);
137  return 1;
138 }
static int current_profile
A number and a text describing the type of media in aquired drive.
Definition: libburner.c:100
static char drive_adr[BURN_DRIVE_ADR_LEN]
The setup parameters of libburner.
Definition: libburner.c:617
int burn_disc_get_profile(struct burn_drive *d, int *pno, char name[80])
Tells the MMC Profile identifier of the loaded media.
int libburner_aquire_by_driveno(int *drive_no)
This method demonstrates how to use libburn without knowing a persistent drive address in advance...
Definition: libburner.c:190
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 systemw...
Definition: libburner.c:145
static struct burn_drive_info * drive_list
Overview.
Definition: libburner.c:89
static int driveno
Definition: libburner.c:618
static char current_profile_name[80]
Definition: libburner.c:101
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 293 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().

294 {
295  enum burn_disc_status disc_state;
296  struct burn_progress p;
297  double percent = 1.0;
298 
299  disc_state = burn_disc_get_status(drive);
300  printf(
301  "Drive media status: %d (see libburn/libburn.h BURN_DISC_*)\n",
302  disc_state);
303  if (current_profile == 0x13) {
304  ; /* formatted DVD-RW will get blanked to sequential state */
305  } else if (disc_state == BURN_DISC_BLANK) {
306  fprintf(stderr,
307  "IDLE: Blank media detected. Will leave it untouched\n");
308  return 2;
309  } else if (disc_state == BURN_DISC_FULL ||
310  disc_state == BURN_DISC_APPENDABLE) {
311  ; /* this is what libburner is willing to blank */
312  } else if (disc_state == BURN_DISC_EMPTY) {
313  fprintf(stderr,"FATAL: No media detected in drive\n");
314  return 0;
315  } else {
316  fprintf(stderr,
317  "FATAL: Unsuitable drive and media state\n");
318  return 0;
319  }
320  if(!burn_disc_erasable(drive)) {
321  fprintf(stderr,
322  "FATAL : Media is not of erasable type\n");
323  return 0;
324  }
325  /* Switch to asynchronous signal handling for the time of waiting */
326  burn_set_signal_handling("libburner : ", NULL, 0x30);
327 
328  printf("Beginning to %s-blank media.\n", (blank_fast?"fast":"full"));
329  burn_disc_erase(drive, blank_fast);
330 
331  sleep(1);
332  while (burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) {
333  if(p.sectors>0 && p.sector>=0) /* display 1 to 99 percent */
334  percent = 1.0 + ((double) p.sector+1.0)
335  / ((double) p.sectors) * 98.0;
336  printf("Blanking ( %.1f%% done )\n", percent);
337  sleep(1);
338  }
339  if (burn_is_aborting(0) > 0)
340  return -1;
341  /* Back to synchronous handling */
342  burn_set_signal_handling("libburner : ", NULL, 0x0);
343  printf("Done\n");
344  return 1;
345 }
Operation progress report.
Definition: libburn.h:666
void burn_disc_erase(struct burn_drive *drive, int fast)
Erase a disc in the drive.
enum burn_drive_status burn_drive_get_status(struct burn_drive *drive, struct burn_progress *p)
Returns the progress and status of a drive.
int burn_disc_erasable(struct burn_drive *d)
Tells whether a disc can be erased or not.
int burn_is_aborting(int flag)
burn_disc_status
Possible status of the drive in regard to the disc in it.
Definition: libburn.h:228
The drive is not in an operation.
Definition: libburn.h:292
There is no disc at all in the drive.
Definition: libburn.h:244
static int current_profile
A number and a text describing the type of media in aquired drive.
Definition: libburner.c:100
void burn_set_signal_handling(void *handle, burn_abort_handler_t handler, int mode)
Control built-in signal handling.
There is a disc with data on it in the drive.
Definition: libburn.h:262
There is an incomplete disc in the drive.
Definition: libburn.h:251
The drive holds a blank disc.
Definition: libburn.h:241
enum burn_disc_status burn_disc_get_status(struct burn_drive *drive)
Returns what kind of disc a drive is holding.
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 360 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().

361 {
362  struct burn_progress p;
363  double percent = 1.0;
364  int ret, status, num_formats, format_flag= 0;
365  off_t size = 0;
366  unsigned dummy;
367  enum burn_disc_status disc_state;
368 
369  if (current_profile == 0x13) {
370  fprintf(stderr, "IDLE: DVD-RW media is already formatted\n");
371  return 2;
372  } else if (current_profile == 0x41 || current_profile == 0x43) {
373  disc_state = burn_disc_get_status(drive);
374  if (disc_state != BURN_DISC_BLANK && current_profile == 0x41) {
375  fprintf(stderr,
376  "FATAL: BD-R is not blank. Cannot format.\n");
377  return 0;
378  }
379  ret = burn_disc_get_formats(drive, &status, &size, &dummy,
380  &num_formats);
381  if (ret > 0 && status != BURN_FORMAT_IS_UNFORMATTED) {
382  fprintf(stderr,
383  "IDLE: BD media is already formatted\n");
384  return 2;
385  }
386  size = 0; /* does not really matter */
387  format_flag = 3<<1; /* format to default size, no quick */
388  } else if (current_profile == 0x14) { /* sequential DVD-RW */
389  size = 128 * 1024 * 1024;
390  format_flag = 1; /* write initial 128 MiB */
391  } else {
392  fprintf(stderr, "FATAL: Can only format DVD-RW or BD\n");
393  return 0;
394  }
395  burn_set_signal_handling("libburner : ", NULL, 0x30);
396 
397  printf("Beginning to format media.\n");
398  burn_disc_format(drive, size, format_flag);
399 
400  sleep(1);
401  while (burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) {
402  if(p.sectors>0 && p.sector>=0) /* display 1 to 99 percent */
403  percent = 1.0 + ((double) p.sector+1.0)
404  / ((double) p.sectors) * 98.0;
405  printf("Formatting ( %.1f%% done )\n", percent);
406  sleep(1);
407  }
408  if (burn_is_aborting(0) > 0)
409  return -1;
410  burn_set_signal_handling("libburner : ", NULL, 0x0);
413  if (current_profile == 0x14 || current_profile == 0x13)
414  printf("Media type now: %4.4xh \"%s\"\n",
416  if (current_profile == 0x14) {
417  fprintf(stderr,
418  "FATAL: Failed to change media profile to desired value\n");
419  return 0;
420  }
421  return 1;
422 }
Operation progress report.
Definition: libburn.h:666
enum burn_drive_status burn_drive_get_status(struct burn_drive *drive, struct burn_progress *p)
Returns the progress and status of a drive.
#define BURN_FORMAT_IS_UNFORMATTED
Possible formatting status values.
Definition: libburn.h:1692
int burn_is_aborting(int flag)
burn_disc_status
Possible status of the drive in regard to the disc in it.
Definition: libburn.h:228
The drive is not in an operation.
Definition: libburn.h:292
int burn_disc_get_formats(struct burn_drive *drive, int *status, off_t *size, unsigned *bl_sas, int *num_formats)
Inquire the formatting status, the associated sizes and the number of available formats.
static int current_profile
A number and a text describing the type of media in aquired drive.
Definition: libburner.c:100
void burn_set_signal_handling(void *handle, burn_abort_handler_t handler, int mode)
Control built-in signal handling.
void burn_disc_format(struct burn_drive *drive, off_t size, int flag)
Format media for use with libburn.
int burn_disc_get_profile(struct burn_drive *d, int *pno, char name[80])
Tells the MMC Profile identifier of the loaded media.
static struct burn_drive_info * drive_list
Overview.
Definition: libburner.c:89
static char current_profile_name[80]
Definition: libburner.c:101
The drive holds a blank disc.
Definition: libburn.h:241
enum burn_disc_status burn_disc_get_status(struct burn_drive *drive)
Returns what kind of disc a drive is holding.
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 440 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, source_adr_count, and burn_progress::track.

Referenced by main().

443 {
444  struct burn_source *data_src, *fifo_src[99];
445  struct burn_disc *target_disc;
446  struct burn_session *session;
447  struct burn_write_opts *burn_options;
448  enum burn_disc_status disc_state;
449  struct burn_track *track, *tracklist[99];
450  struct burn_progress progress;
451  time_t start_time;
452  int last_sector = 0, padding = 0, trackno, unpredicted_size = 0, fd;
453  int fifo_chunksize = 2352, fifo_chunks = 1783; /* ~ 4 MB fifo */
454  off_t fixed_size;
455  char *adr, reasons[BURN_REASONS_LEN];
456  struct stat stbuf;
457 
458  if (all_tracks_type != BURN_AUDIO) {
460  /* a padding of 300 kiB helps to avoid the read-ahead bug */
461  padding = 300*1024;
462  fifo_chunksize = 2048;
463  fifo_chunks = 2048; /* 4 MB fifo */
464  }
465 
466  target_disc = burn_disc_create();
467  session = burn_session_create();
468  burn_disc_add_session(target_disc, session, BURN_POS_END);
469 
470  for (trackno = 0 ; trackno < source_adr_count; trackno++) {
471  tracklist[trackno] = track = burn_track_create();
472  burn_track_define_data(track, 0, padding, 1, all_tracks_type);
473 
474  /* Open file descriptor to source of track data */
475  adr = source_adr[trackno];
476  fixed_size = 0;
477  if (adr[0] == '-' && adr[1] == 0) {
478  fd = 0;
479  } else {
480  fd = open(adr, O_RDONLY);
481  if (fd>=0)
482  if (fstat(fd,&stbuf)!=-1)
483  if((stbuf.st_mode&S_IFMT)==S_IFREG)
484  fixed_size = stbuf.st_size;
485  }
486  if (fixed_size==0)
487  unpredicted_size = 1;
488 
489  /* Convert this filedescriptor into a burn_source object */
490  data_src = NULL;
491  if (fd>=0)
492  data_src = burn_fd_source_new(fd, -1, fixed_size);
493  if (data_src == NULL) {
494  fprintf(stderr,
495  "FATAL: Could not open data source '%s'.\n",adr);
496  if(errno!=0)
497  fprintf(stderr,"(Most recent system error: %s )\n",
498  strerror(errno));
499  return 0;
500  }
501  /* Install a fifo object on top of that data source object */
502  fifo_src[trackno] = burn_fifo_source_new(data_src,
503  fifo_chunksize, fifo_chunks, 0);
504  if (fifo_src[trackno] == NULL) {
505  fprintf(stderr,
506  "FATAL: Could not create fifo object of 4 MB\n");
507  return 0;
508  }
509 
510  /* Use the fifo object as data source for the track */
511  if (burn_track_set_source(track, fifo_src[trackno])
512  != BURN_SOURCE_OK) {
513  fprintf(stderr,
514  "FATAL: Cannot attach source object to track object\n");
515  return 0;
516  }
517 
518  burn_session_add_track(session, track, BURN_POS_END);
519  printf("Track %d : source is '%s'\n", trackno+1, adr);
520 
521  /* Give up local reference to the data burn_source object */
522  burn_source_free(data_src);
523 
524  } /* trackno loop end */
525 
526  /* Evaluate drive and media */
527  disc_state = burn_disc_get_status(drive);
528  if (disc_state != BURN_DISC_BLANK &&
529  disc_state != BURN_DISC_APPENDABLE) {
530  if (disc_state == BURN_DISC_FULL) {
531  fprintf(stderr, "FATAL: Closed media with data detected. Need blank or appendable media.\n");
532  if (burn_disc_erasable(drive))
533  fprintf(stderr, "HINT: Try --blank_fast\n\n");
534  } else if (disc_state == BURN_DISC_EMPTY)
535  fprintf(stderr,"FATAL: No media detected in drive\n");
536  else
537  fprintf(stderr,
538  "FATAL: Cannot recognize state of drive and media\n");
539  return 0;
540  }
541 
542  burn_options = burn_write_opts_new(drive);
543  burn_write_opts_set_perform_opc(burn_options, 0);
544  burn_write_opts_set_multi(burn_options, !!multi);
545  if(simulate_burn)
546  printf("\n*** Will TRY to SIMULATE burning ***\n\n");
548  burn_drive_set_speed(drive, 0, 0);
549  burn_write_opts_set_underrun_proof(burn_options, 1);
550  if (burn_write_opts_auto_write_type(burn_options, target_disc,
551  reasons, 0) == BURN_WRITE_NONE) {
552  fprintf(stderr, "FATAL: Failed to find a suitable write mode with this media.\n");
553  fprintf(stderr, "Reasons given:\n%s\n", reasons);
554  return 0;
555  }
556  burn_set_signal_handling("libburner : ", NULL, 0x30);
557 
558  printf("Burning starts. With e.g. 4x media expect up to a minute of zero progress.\n");
559  start_time = time(0);
560  burn_disc_write(burn_options, target_disc);
561 
562  burn_write_opts_free(burn_options);
563  while (burn_drive_get_status(drive, NULL) == BURN_DRIVE_SPAWNING)
564  usleep(100002);
565  while (burn_drive_get_status(drive, &progress) != BURN_DRIVE_IDLE) {
566  if (progress.sectors <= 0 ||
567  (progress.sector >= progress.sectors - 1 &&
568  !unpredicted_size) ||
569  (unpredicted_size && progress.sector == last_sector))
570  printf(
571  "Thank you for being patient since %d seconds.",
572  (int) (time(0) - start_time));
573  else if(unpredicted_size)
574  printf("Track %d : sector %d", progress.track+1,
575  progress.sector);
576  else
577  printf("Track %d : sector %d of %d",progress.track+1,
578  progress.sector, progress.sectors);
579  last_sector = progress.sector;
580  if (progress.track >= 0 && progress.track < source_adr_count) {
581  int size, free_bytes, ret;
582  char *status_text;
583 
585  fifo_src[progress.track], &size, &free_bytes,
586  &status_text);
587  if (ret >= 0 )
588  printf(" [fifo %s, %2d%% fill]", status_text,
589  (int) (100.0 - 100.0 *
590  ((double) free_bytes) /
591  (double) size));
592  }
593  printf("\n");
594  sleep(1);
595  }
596  printf("\n");
597 
598  for (trackno = 0 ; trackno < source_adr_count; trackno++) {
599  burn_source_free(fifo_src[trackno]);
600  burn_track_free(tracklist[trackno]);
601  }
602  burn_session_free(session);
603  burn_disc_free(target_disc);
604  if (burn_is_aborting(0) > 0)
605  return -1;
606  if (multi && current_profile != 0x1a && current_profile != 0x13 &&
607  current_profile != 0x12 && current_profile != 0x43)
608  /* not with DVD+RW, formatted DVD-RW, DVD-RAM, BD-RE */
609  printf("NOTE: Media left appendable.\n");
610  if (simulate_burn)
611  printf("\n*** Did TRY to SIMULATE burning ***\n\n");
612  return 1;
613 }
void burn_disc_write(struct burn_write_opts *o, struct burn_disc *disc)
Write a disc in the drive.
void burn_write_opts_free(struct burn_write_opts *opts)
Frees a write_opts struct created with burn_write_opts_new.
Operation progress report.
Definition: libburn.h:666
static int all_tracks_type
Definition: libburner.c:624
struct burn_write_opts * burn_write_opts_new(struct burn_drive *drive)
Creates a write_opts struct for burning to the specified drive.
enum burn_drive_status burn_drive_get_status(struct burn_drive *drive, struct burn_progress *p)
Returns the progress and status of a drive.
The library is spawning the processes to handle a pending operation (A read/write/etc is about to sta...
Definition: libburn.h:296
int burn_disc_add_session(struct burn_disc *d, struct burn_session *s, unsigned int pos)
Add a session to a disc at a specific position, increasing the sessions's reference count...
int burn_disc_erasable(struct burn_drive *d)
Tells whether a disc can be erased or not.
In replies this indicates that not any writing will work.
Definition: libburn.h:184
int burn_is_aborting(int flag)
void burn_session_free(struct burn_session *s)
Free a session (and decrease reference count on all tracks inside)
int burn_write_opts_set_underrun_proof(struct burn_write_opts *opts, int underrun_proof)
Controls buffer underrun prevention.
static int source_adr_count
Definition: libburner.c:621
struct burn_disc * burn_disc_create(void)
Create a new disc.
burn_disc_status
Possible status of the drive in regard to the disc in it.
Definition: libburn.h:228
The drive is not in an operation.
Definition: libburn.h:292
struct burn_track * burn_track_create(void)
Create a track.
There is no disc at all in the drive.
Definition: libburn.h:244
static int current_profile
A number and a text describing the type of media in aquired drive.
Definition: libburner.c:100
void burn_drive_set_speed(struct burn_drive *d, int read, int write)
Sets drive read and write speed Note: "k" is 1000, not 1024.
void burn_set_signal_handling(void *handle, burn_abort_handler_t handler, int mode)
Control built-in signal handling.
#define BURN_AUDIO
Track mode - audio 2352 bytes per sector.
Definition: libburn.h:110
Data source interface for tracks.
Definition: libburn.h:459
void burn_track_free(struct burn_track *t)
Free a track.
static char source_adr[99][4096]
Definition: libburner.c:620
void burn_disc_free(struct burn_disc *d)
Delete disc and decrease the reference count on all its sessions.
void burn_source_free(struct burn_source *s)
Free a burn_source (decrease its refcount and maybe free it)
struct burn_source * burn_fd_source_new(int datafd, int subfd, off_t size)
Creates a data source for an image file (a track) from an open readable filedescriptor, an eventually open readable subcodes file descriptor and eventually a fixed size in bytes.
void burn_write_opts_set_multi(struct burn_write_opts *opts, int multi)
Sets the multi flag which eventually marks the emerging session as not being the last one and thus cr...
#define BURN_MODE1
Track mode - mode 1 data 2048 bytes user data, and all the LEC money can buy.
Definition: libburn.h:89
#define BURN_POS_END
Definition: libburn.h:73
There is a disc with data on it in the drive.
Definition: libburn.h:262
struct burn_source * burn_fifo_source_new(struct burn_source *inp, int chunksize, int chunks, int flag)
Creates a fifo which acts as proxy for an already existing data source.
static int simulate_burn
Definition: libburner.c:623
int burn_session_add_track(struct burn_session *s, struct burn_track *t, unsigned int pos)
Add a track to a session at specified position.
enum burn_source_status burn_track_set_source(struct burn_track *t, struct burn_source *s)
Set the track's data source.
There is an incomplete disc in the drive.
Definition: libburn.h:251
The source is ok.
Definition: libburn.h:280
void burn_track_define_data(struct burn_track *t, int offset, int tail, int pad, int mode)
Define the data in a track.
void burn_write_opts_set_perform_opc(struct burn_write_opts *opts, int opc)
Sets whether to use opc or not with the write_opts struct.
The drive holds a blank disc.
Definition: libburn.h:241
enum burn_disc_status burn_disc_get_status(struct burn_drive *drive)
Returns what kind of disc a drive is holding.
enum burn_write_types burn_write_opts_auto_write_type(struct burn_write_opts *opts, struct burn_disc *disc, char reasons[BURN_REASONS_LEN], int flag)
As an alternative to burn_write_opts_set_write_type() this function tries to find a suitable write ty...
#define BURN_REASONS_LEN
The length of a rejection reasons string for burn_precheck_write() and burn_write_opts_auto_write_typ...
Definition: libburn.h:1756
int burn_write_opts_set_simulate(struct burn_write_opts *opts, int sim)
Sets the simulate value for the write_opts struct .
int burn_fifo_inquire_status(struct burn_source *fifo, int *size, int *free_bytes, char **status_text)
Inquires state and fill parameters of a fifo burn_source which was created by burn_fifo_source_new() ...
struct burn_session * burn_session_create(void)
Create a new session.
int libburner_setup ( int  argc,
char **  argv 
)

Converts command line arguments into above setup parameters.

Definition at line 629 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().

630 {
631  int i, insuffient_parameters = 0, print_help = 0;
632 
633  for (i = 1; i < argc; ++i) {
634  if (!strcmp(argv[i], "--audio")) {
636 
637  } else if (!strcmp(argv[i], "--blank_fast")) {
638  do_blank = 1;
639 
640  } else if (!strcmp(argv[i], "--blank_full")) {
641  do_blank = 2;
642 
643  } else if (!strcmp(argv[i], "--burn_for_real")) {
644  simulate_burn = 0;
645 
646  } else if (!strcmp(argv[i], "--drive")) {
647  ++i;
648  if (i >= argc) {
649  fprintf(stderr,"--drive requires an argument\n");
650  return 1;
651  } else if (strcmp(argv[i], "-") == 0) {
652  drive_adr[0] = 0;
653  driveno = -1;
654  } else if (isdigit(argv[i][0])) {
655  drive_adr[0] = 0;
656  driveno = atoi(argv[i]);
657  } else {
658  if(strlen(argv[i]) >= BURN_DRIVE_ADR_LEN) {
659  fprintf(stderr,"--drive address too long (max. %d)\n",
661  return 2;
662  }
663  strcpy(drive_adr, argv[i]);
664  }
665  } else if ((!strcmp(argv[i], "--format_overwrite")) ||
666  (!strcmp(argv[i], "--format"))) {
667  do_blank = 101;
668 
669  } else if (!strcmp(argv[i], "--multi")) {
670  do_multi = 1;
671 
672  } else if (!strcmp(argv[i], "--stdin_size")) { /* obsoleted */
673  i++;
674 
675  } else if (!strcmp(argv[i], "--try_to_simulate")) {
676  simulate_burn = 1;
677 
678  } else if (!strcmp(argv[i], "--help")) {
679  print_help = 1;
680 
681  } else if (!strncmp(argv[i], "--",2)) {
682  fprintf(stderr, "Unidentified option: %s\n", argv[i]);
683  return 7;
684  } else {
685  if(strlen(argv[i]) >= 4096) {
686  fprintf(stderr, "Source address too long (max. %d)\n", 4096-1);
687  return 5;
688  }
689  if(source_adr_count >= 99) {
690  fprintf(stderr, "Too many tracks (max. 99)\n");
691  return 6;
692  }
693  strcpy(source_adr[source_adr_count], argv[i]);
695  }
696  }
697  insuffient_parameters = 1;
698  if (driveno < 0)
699  insuffient_parameters = 0;
700  if (source_adr_count > 0)
701  insuffient_parameters = 0;
702  if (do_blank)
703  insuffient_parameters = 0;
704  if (print_help || insuffient_parameters ) {
705  printf("Usage: %s\n", argv[0]);
706  printf(" [--drive <address>|<driveno>|\"-\"] [--audio]\n");
707  printf(" [--blank_fast|--blank_full|--format] [--try_to_simulate]\n");
708  printf(" [--multi] [<one or more imagefiles>|\"-\"]\n");
709  printf("Examples\n");
710  printf("A bus scan (needs rw-permissions to see a drive):\n");
711  printf(" %s --drive -\n",argv[0]);
712  printf("Burn a file to drive chosen by number, leave appendable:\n");
713  printf(" %s --drive 0 --multi my_image_file\n", argv[0]);
714  printf("Burn a file to drive chosen by persistent address, close:\n");
715  printf(" %s --drive /dev/hdc my_image_file\n", argv[0]);
716  printf("Blank a used CD-RW (is combinable with burning in one run):\n");
717  printf(" %s --drive /dev/hdc --blank_fast\n",argv[0]);
718  printf("Blank a used DVD-RW (is combinable with burning in one run):\n");
719  printf(" %s --drive /dev/hdc --blank_full\n",argv[0]);
720  printf("Format a DVD-RW, BD-RE or BD-R:\n");
721  printf(" %s --drive /dev/hdc --format\n", argv[0]);
722  printf("Burn two audio tracks (to CD only):\n");
723  printf(" lame --decode -t /path/to/track1.mp3 track1.cd\n");
724  printf(" test/dewav /path/to/track2.wav -o track2.cd\n");
725  printf(" %s --drive /dev/hdc --audio track1.cd track2.cd\n", argv[0]);
726  printf("Burn a compressed afio archive on-the-fly:\n");
727  printf(" ( cd my_directory ; find . -print | afio -oZ - ) | \\\n");
728  printf(" %s --drive /dev/hdc -\n", argv[0]);
729  printf("To be read from *not mounted* media via: afio -tvZ /dev/hdc\n");
730  if (insuffient_parameters)
731  return 6;
732  }
733  return 0;
734 }
static int all_tracks_type
Definition: libburner.c:624
static int do_multi
Definition: libburner.c:622
#define BURN_DRIVE_ADR_LEN
Maximum length+1 to expect with a drive device file address string.
Definition: libburn.h:1037
static int source_adr_count
Definition: libburner.c:621
static char drive_adr[BURN_DRIVE_ADR_LEN]
The setup parameters of libburner.
Definition: libburner.c:617
#define BURN_AUDIO
Track mode - audio 2352 bytes per sector.
Definition: libburn.h:110
static char source_adr[99][4096]
Definition: libburner.c:620
static int driveno
Definition: libburner.c:618
static int simulate_burn
Definition: libburner.c:623
static int do_blank
Definition: libburner.c:619
int main ( int  argc,
char **  argv 
)

Note: driveno might change its value in this call

Definition at line 737 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.

738 {
739  int ret;
740 
741  /* A warning to programmers who start their own projekt from here. */
742  if (sizeof(off_t) != 8) {
743  fprintf(stderr,
744  "\nFATAL: Compile time misconfiguration. off_t is not 64 bit.\n\n");
745  exit(39);
746  }
747 
748  ret = libburner_setup(argc, argv);
749  if (ret)
750  exit(ret);
751 
752  printf("Initializing libburnia-project.org ...\n");
753  if (burn_initialize())
754  printf("Done\n");
755  else {
756  printf("FAILED\n");
757  fprintf(stderr,"\nFATAL: Failed to initialize.\n");
758  exit(33);
759  }
760 
761  /* Print messages of severity SORRY or more directly to stderr */
762  burn_msgs_set_severities("NEVER", "SORRY", "libburner : ");
763 
764  /* Activate the synchronous signal handler which eventually will try to
765  properly shutdown drive and library on aborting events. */
766  burn_set_signal_handling("libburner : ", NULL, 0x0);
767 
768  /** Note: driveno might change its value in this call */
770  if (ret<=0) {
771  fprintf(stderr,"\nFATAL: Failed to aquire drive.\n");
772  { ret = 34; goto finish_libburn; }
773  }
774  if (ret == 2)
775  { ret = 0; goto release_drive; }
776  if (do_blank) {
777  if (do_blank > 100)
778  ret = libburner_format(drive_list[driveno].drive);
779  else
781  do_blank == 1);
782  if (ret<=0)
783  { ret = 36; goto release_drive; }
784  }
785  if (source_adr_count > 0) {
786  ret = libburner_payload(drive_list[driveno].drive,
789  if (ret<=0)
790  { ret = 38; goto release_drive; }
791  }
792  ret = 0;
793 release_drive:;
794  if (drive_is_grabbed)
796 
797 finish_libburn:;
798  if (burn_is_aborting(0) > 0) {
799  burn_abort(4400, burn_abort_pacifier, "libburner : ");
800  fprintf(stderr,"\nlibburner run aborted\n");
801  exit(1);
802  }
803  /* This app does not bother to know about exact scan state.
804  Better to accept a memory leak here. We are done anyway. */
805  /* burn_drive_info_free(drive_list); */
806  burn_finish();
807  exit(ret);
808 }
static int all_tracks_type
Definition: libburner.c:624
static int do_multi
Definition: libburner.c:622
static int drive_is_grabbed
This variable indicates wether the drive is grabbed and must be finally released. ...
Definition: libburner.c:97
int burn_is_aborting(int flag)
static int source_adr_count
Definition: libburner.c:621
int burn_msgs_set_severities(char *queue_severity, char *print_severity, char *print_id)
Control queueing and stderr printing of messages from libburn.
int burn_abort(int patience, int(*pacifier_func)(void *handle, int patience, int elapsed), void *handle)
Abort any running drive operation and eventually call burn_finish().
void burn_finish(void)
Shutdown the library.
int burn_initialize(void)
Initialize the library.
void burn_set_signal_handling(void *handle, burn_abort_handler_t handler, int mode)
Control built-in signal handling.
int burn_abort_pacifier(void *handle, int patience, int elapsed)
A pacifier function suitable for burn_abort.
static char drive_adr[BURN_DRIVE_ADR_LEN]
The setup parameters of libburner.
Definition: libburner.c:617
static char source_adr[99][4096]
Definition: libburner.c:620
int libburner_format(struct burn_drive *drive)
Formats unformatted DVD-RW to profile 0013h "Restricted Overwrite" which needs no blanking for re-use...
Definition: libburner.c:360
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.
Definition: libburner.c:440
int libburner_aquire_drive(char *drive_adr, int *driveno)
You need to aquire a drive before burning.
Definition: libburner.c:123
void burn_drive_release(struct burn_drive *drive, int eject)
Release a drive.
static struct burn_drive_info * drive_list
Overview.
Definition: libburner.c:89
static int driveno
Definition: libburner.c:618
int libburner_setup(int argc, char **argv)
Converts command line arguments into above setup parameters.
Definition: libburner.c:629
static int simulate_burn
Definition: libburner.c:623
static int do_blank
Definition: libburner.c:619
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.
Definition: libburner.c:293

Variable Documentation

int all_tracks_type = BURN_MODE1
static

Definition at line 624 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 100 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 101 of file libburner.c.

Referenced by libburner_aquire_drive(), and libburner_format().

int do_blank = 0
static

Definition at line 619 of file libburner.c.

Referenced by libburner_setup(), and main().

int do_multi = 0
static

Definition at line 622 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 617 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 93 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 97 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("libburner : ", NULL, 0x0) 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 twoi 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 as shown in 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. See libburner_payload()

These three functions switch temporarily to a non-fatal signal handler while they are waiting for the drive to become idle again: burn_set_signal_handling("libburner : ", NULL, 0x30) After the waiting loop ended, they check for eventual abort events by burn_is_aborting(0) The 0x30 handler will eventually execute burn_abort() but not wait for the drive to become idle and not call exit(). This is needed because the worker threads might block as long as the signal handler has not returned. The 0x0 handler would wait for them to finish. Take this into respect when implementing own signal handlers.

When everything is done, main() releases the drive and shuts down libburn: burn_drive_release(); burn_finish()

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 89 of file libburner.c.

int driveno = 0
static

Definition at line 618 of file libburner.c.

Referenced by libburner_setup(), and main().

int simulate_burn = 0
static

Definition at line 623 of file libburner.c.

Referenced by libburner_setup(), and main().

char source_adr[99][4096]
static

Definition at line 620 of file libburner.c.

Referenced by libburner_setup(), and main().

int source_adr_count = 0
static

Definition at line 621 of file libburner.c.

Referenced by libburner_payload(), libburner_setup(), and main().