2006-08-18 17:03:41 +00:00
|
|
|
|
|
|
|
/*
|
|
|
|
cdrskin.c , Copyright 2006 Thomas Schmitt <scdbackup@gmx.net>
|
2006-09-07 11:55:42 +00:00
|
|
|
Provided under GPL. See future commitment below.
|
2006-08-18 17:03:41 +00:00
|
|
|
|
|
|
|
A cdrecord compatible command line interface for libburn.
|
|
|
|
|
|
|
|
This project is neither directed against original cdrecord nor does it exploit
|
|
|
|
any source code of said program. It rather tries to be an alternative method
|
|
|
|
to burn CD which is not based on the same code as cdrecord.
|
|
|
|
See also : http://scdbackup.sourceforge.net/cdrskin_eng.html
|
|
|
|
|
|
|
|
Interested users of cdrecord are encouraged to contribute further option
|
|
|
|
implementations as they need them. Contributions will get published under GPL
|
|
|
|
but it is essential that the authors allow a future release under LGPL and/or
|
|
|
|
BSD license.
|
|
|
|
|
|
|
|
There is a script test/cdrecord_spy.sh which may be installed between
|
|
|
|
the cdrecord command and real cdrecord in order to learn about the options
|
|
|
|
used by your favorite cdrecord frontend. Edit said script and install it
|
|
|
|
according to the instructions given inside.
|
|
|
|
|
|
|
|
The implementation of an option would probably consist of
|
|
|
|
- necessary structure members for structs CdrpreskiN and/or CdrskiN
|
|
|
|
- code in Cdrpreskin_setup() and Cdrskin_setup() which converts
|
|
|
|
argv[i] into CdrpreskiN/CdrskiN members (or into direct actions)
|
|
|
|
- removal of option from ignore list "ignored_partial_options" resp.
|
|
|
|
"ignored_full_options" in Cdrskin_setup()
|
|
|
|
- functions which implement the option's run time functionality
|
|
|
|
- eventually calls of those functions in Cdrskin_run()
|
|
|
|
- changes to be made within Cdrskin_burn() or Cdrskin_blank() or other
|
|
|
|
existing methods
|
|
|
|
See option blank= for an example.
|
|
|
|
|
2006-08-25 18:21:03 +00:00
|
|
|
------------------------------------------------------------------------------
|
|
|
|
About compliance with *strong urge* of API towards burn_drive_scan_and_grab()
|
|
|
|
|
2006-08-27 19:28:37 +00:00
|
|
|
For a more comprehensive example of the advised way to behave with libburn
|
2006-09-01 08:49:31 +00:00
|
|
|
see test/libburner.c .
|
2006-08-27 19:28:37 +00:00
|
|
|
|
2006-08-25 18:21:03 +00:00
|
|
|
cdrskin was the initiator of the whitelist functionality within libburn.
|
|
|
|
Now it has problems to obviously comply with the new API best practice
|
|
|
|
presciptions literally. Therefore this explanation:
|
|
|
|
|
|
|
|
On start it restricts the library to a single drive if it already knows the
|
|
|
|
persistent address by option dev= . This is done with a combination of
|
|
|
|
burn_drive_add_whitelist() and burn_drive_scan(). Not compliant to the
|
|
|
|
literal strong urge but in fact exactly fulfilling the reason for that
|
|
|
|
urge in the API: any scanned drive might be opened exclusively after
|
|
|
|
burn_drive_scan(). It is kernel dependent wether this behavior is on, off
|
|
|
|
or switchable. The sysdamin will want it on - but only for one drive.
|
|
|
|
|
|
|
|
So with dev=... cdrskin complies to the spirit of the strong urge.
|
|
|
|
Without dev=... it has to leave out the whitelist in order to enable bus
|
|
|
|
scanning and implicit drive address 0. A tradition of 9 months shall not
|
2006-09-12 17:59:48 +00:00
|
|
|
be broken. So burns without dev= will stay possible - but harmless only
|
|
|
|
on single drive systems.
|
|
|
|
|
|
|
|
Burns without dev= resp. with dev=number are harmless on multi-drive systems.
|
|
|
|
|
|
|
|
This is because Cdrskin_grab_drive() either drops the unwanted drives or
|
|
|
|
it enforces a restart of the library with the desired drive's persistent
|
|
|
|
address. This restart then really uses the strongly urged function
|
|
|
|
burn_drive_scan_and_grab().
|
2006-08-25 18:21:03 +00:00
|
|
|
Thus, cdrskin complies with the new spirit of API by closing down libburn
|
2006-09-12 17:59:48 +00:00
|
|
|
or by dropping unused drives as soon as the persistent drive address is
|
|
|
|
known and the drive is to be used with a long running operation. To my
|
|
|
|
knowlege all long running operations in cdrskin need a grabbed drive.
|
2006-08-25 18:21:03 +00:00
|
|
|
|
|
|
|
This spaghetti approach seems necessary to keep small the impact of new API
|
|
|
|
urge on cdrskin's stability. cdrskin suffers from having donated the body
|
|
|
|
parts which have been transplanted to libburn in order to create
|
|
|
|
burn_drive_scan_and_grab() . The desired sysadmin friendlyness was already
|
|
|
|
achieved by most cdrskin runs. The remaining problem situations should now
|
|
|
|
be defused by releasing any short time grabbed flocks of drives during the
|
|
|
|
restart of libburn.
|
2006-08-27 19:28:37 +00:00
|
|
|
|
2006-08-29 09:16:21 +00:00
|
|
|
------------------------------------------------------------------------------
|
|
|
|
This program is currently copyright Thomas Schmitt only.
|
2006-09-03 11:24:30 +00:00
|
|
|
The copyrights of several components of libburn.pykix.org are willfully tangled
|
|
|
|
at toplevel to form an irrevocable commitment to true open source spirit.
|
|
|
|
We have chosen the GPL for legal compatibility and clearly express that it
|
|
|
|
shall not hamper the use of our software by non-GPL applications which show
|
|
|
|
otherwise the due respect to the open source community.
|
|
|
|
See toplevel README and cdrskin/README for that commitment.
|
|
|
|
|
|
|
|
For a short time, this place showed a promise to release a BSD license on
|
|
|
|
mere request. I have to retract that promise now, and replace it by the
|
|
|
|
promise to make above commitment reality in a way that any BSD conformant
|
|
|
|
usage in due open source spirit will be made possible somehow and in the
|
|
|
|
particular special case. I will not raise public protest if you spawn yourself
|
|
|
|
a BSD license from an (outdated) cdrskin.c which still bears that old promise.
|
|
|
|
Note that this extended commitment is valid only for cdrskin.[ch],
|
|
|
|
cdrfifo.[ch] and cleanup.[ch], but not for libburn.pykix.org as a whole.
|
|
|
|
|
2006-09-07 11:55:42 +00:00
|
|
|
cdrskin is originally inspired by libburn-0.2/test/burniso.c :
|
|
|
|
(c) Derek Foreman <derek@signalmarketing.com> and Ben Jansens <xor@orodu.net>
|
|
|
|
|
2006-08-25 18:21:03 +00:00
|
|
|
------------------------------------------------------------------------------
|
2006-08-18 17:03:41 +00:00
|
|
|
|
|
|
|
Compilation within cdrskin-* :
|
|
|
|
|
|
|
|
cd cdrskin
|
|
|
|
cc -g -I.. -DCdrskin_build_timestamP='...' \
|
|
|
|
-o cdrskin cdrskin.c cdrfifo.c cleanup.c \
|
|
|
|
-L../libburn/.libs -lburn -lpthread
|
|
|
|
|
|
|
|
or
|
|
|
|
|
|
|
|
cd ..
|
|
|
|
cc -g -I. -DCdrskin_build_timestamP='...' \
|
|
|
|
-o cdrskin/cdrskin cdrskin/cdrskin.c cdrskin/cdrfifo.c cdrskin/cleanup.c \
|
|
|
|
libburn/async.o libburn/crc.o libburn/debug.o libburn/drive.o \
|
|
|
|
libburn/file.o libburn/init.o libburn/lec.o libburn/message.o \
|
|
|
|
libburn/mmc.o libburn/options.o libburn/sbc.o libburn/sector.o \
|
|
|
|
libburn/sg.o libburn/spc.o libburn/source.o libburn/structure.o \
|
|
|
|
libburn/toc.o libburn/util.o libburn/write.o \
|
|
|
|
-lpthread
|
|
|
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
|
|
/** The official program version */
|
2006-09-12 17:08:41 +00:00
|
|
|
#ifndef Cdrskin_prog_versioN
|
2006-09-21 09:37:42 +00:00
|
|
|
#define Cdrskin_prog_versioN "0.2.3"
|
2006-09-12 17:08:41 +00:00
|
|
|
#endif
|
2006-08-18 17:03:41 +00:00
|
|
|
|
|
|
|
/** The source code release timestamp */
|
|
|
|
#include "cdrskin_timestamp.h"
|
|
|
|
#ifndef Cdrskin_timestamP
|
|
|
|
#define Cdrskin_timestamP "-none-given-"
|
|
|
|
#endif
|
|
|
|
|
|
|
|
/** The binary build timestamp is to be set externally by the compiler */
|
|
|
|
#ifndef Cdrskin_build_timestamP
|
|
|
|
#define Cdrskin_build_timestamP "-none-given-"
|
|
|
|
#endif
|
|
|
|
|
2006-09-21 17:29:41 +00:00
|
|
|
|
|
|
|
#ifdef Cdrskin_libburn_versioN
|
|
|
|
#undef Cdrskin_libburn_versioN
|
2006-08-18 17:03:41 +00:00
|
|
|
#endif
|
|
|
|
|
|
|
|
/** use this to accomodate to the CVS version as of Feb 20, 2006
|
|
|
|
#define Cdrskin_libburn_cvs_A60220_tS 1
|
|
|
|
*/
|
|
|
|
#ifdef Cdrskin_libburn_cvs_A60220_tS
|
|
|
|
|
|
|
|
#define Cdrskin_libburn_versioN "0.2.tsA60220"
|
|
|
|
#define Cdrskin_libburn_no_burn_preset_device_opeN 1
|
2006-09-21 18:57:01 +00:00
|
|
|
#ifndef Cdrskin_oldfashioned_api_usE
|
|
|
|
#define Cdrskin_oldfashioned_api_usE 1
|
|
|
|
#endif
|
2006-08-18 17:03:41 +00:00
|
|
|
|
|
|
|
#endif /* Cdrskin_libburn_cvs_A60220_tS */
|
|
|
|
|
|
|
|
|
2006-09-15 09:26:25 +00:00
|
|
|
#ifdef Cdrskin_libburn_0_2_2
|
2006-09-12 17:08:41 +00:00
|
|
|
#define Cdrskin_libburn_versioN "0.2.2"
|
|
|
|
#define Cdrskin_libburn_from_pykix_svN 1
|
|
|
|
#endif
|
|
|
|
|
2006-09-21 09:37:42 +00:00
|
|
|
#ifdef Cdrskin_libburn_0_2_3
|
|
|
|
#define Cdrskin_libburn_versioN "0.2.3"
|
|
|
|
#define Cdrskin_libburn_from_pykix_svN 1
|
2006-09-22 13:30:32 +00:00
|
|
|
#define Cdrskin_libburn_has_is_enumerablE 1
|
2006-09-22 17:01:26 +00:00
|
|
|
#define Cdrskin_libburn_has_convert_fs_adR 1
|
2006-09-23 11:47:46 +00:00
|
|
|
#define Cdrskin_libburn_has_convert_scsi_adR 1
|
2006-09-24 17:16:01 +00:00
|
|
|
#define Cdrskin_libburn_has_burn_msgS 1
|
2006-09-21 09:37:42 +00:00
|
|
|
#endif
|
|
|
|
|
2006-09-21 17:29:41 +00:00
|
|
|
#ifndef Cdrskin_libburn_versioN
|
2006-09-23 11:47:46 +00:00
|
|
|
#define Cdrskin_libburn_versioN "0.2.2"
|
2006-09-21 17:29:41 +00:00
|
|
|
#define Cdrskin_libburn_from_pykix_svN 1
|
|
|
|
#endif
|
|
|
|
|
2006-09-12 17:08:41 +00:00
|
|
|
#ifdef Cdrskin_libburn_from_pykix_svN
|
2006-09-21 17:29:41 +00:00
|
|
|
|
2006-08-31 11:14:27 +00:00
|
|
|
#define Cdrskin_libburn_does_ejecT 1
|
|
|
|
#define Cdrskin_libburn_has_drive_get_adR 1
|
2006-09-01 08:49:31 +00:00
|
|
|
#define Cdrskin_progress_track_does_worK 1
|
2006-09-08 20:17:18 +00:00
|
|
|
#define Cdrskin_is_erasable_on_load_does_worK 1
|
|
|
|
#define Cdrskin_grab_abort_does_worK 1
|
2006-09-01 08:49:31 +00:00
|
|
|
|
2006-08-28 21:28:24 +00:00
|
|
|
#ifdef Cdrskin_new_api_tesT
|
2006-08-31 11:14:27 +00:00
|
|
|
|
2006-09-21 18:57:01 +00:00
|
|
|
/* put macros under test caveat here */
|
|
|
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef Cdrskin_oldfashioned_api_usE
|
2006-09-01 08:49:31 +00:00
|
|
|
|
2006-09-21 18:57:01 +00:00
|
|
|
/* switch back to pre-0.2.2 libburn usage */;
|
2006-08-31 11:14:27 +00:00
|
|
|
|
2006-08-28 21:28:24 +00:00
|
|
|
#endif
|
|
|
|
|
2006-09-12 17:08:41 +00:00
|
|
|
#endif /* Cdrskin_libburn_from_pykix_svN */
|
2006-08-18 17:03:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
#ifndef _LARGEFILE_SOURCE
|
|
|
|
#define _LARGEFILE_SOURCE 1
|
|
|
|
#endif
|
|
|
|
#ifndef _FILE_OFFSET_BITS
|
|
|
|
#define _FILE_OFFSET_BITS 64
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
|
|
/* These macros activate cdrskin workarounds for deficiencies resp.
|
|
|
|
problematic features of libburn which hopefully will change in
|
|
|
|
future. */
|
|
|
|
|
|
|
|
/** Work around the fact that neither /dev/sg0 (kernel 2.4 + ide-scsi) nor
|
2006-09-21 17:29:41 +00:00
|
|
|
/dev/hdc (kernel 2.6) get ejected by icculus.org/burn */
|
2006-08-29 15:29:31 +00:00
|
|
|
#ifndef Cdrskin_libburn_does_ejecT
|
2006-08-18 17:03:41 +00:00
|
|
|
#define Cdrskin_burn_drive_eject_brokeN 1
|
2006-08-29 15:29:31 +00:00
|
|
|
#endif
|
2006-08-18 17:03:41 +00:00
|
|
|
|
|
|
|
/** Work around the fact that after loading media speed report is wrong */
|
|
|
|
#define Cdrskin_atip_speed_brokeN 1
|
|
|
|
|
|
|
|
/** Work around the fact that burn_drive_get_status() always reports to do
|
2006-09-21 17:29:41 +00:00
|
|
|
track 0 in icculus.org/burn */
|
2006-09-01 08:49:31 +00:00
|
|
|
#ifndef Cdrskin_progress_track_does_worK
|
2006-08-18 17:03:41 +00:00
|
|
|
#define Cdrskin_progress_track_brokeN 1
|
2006-09-01 08:49:31 +00:00
|
|
|
#endif
|
2006-08-18 17:03:41 +00:00
|
|
|
|
|
|
|
/** Work around the fact that a drive interrupted at burn_drive_grab() never
|
2006-09-21 17:29:41 +00:00
|
|
|
leaves status BURN_DRIVE_GRABBING in icculus.org/burn */
|
2006-09-07 11:55:42 +00:00
|
|
|
#ifndef Cdrskin_grab_abort_does_worK
|
2006-08-18 17:03:41 +00:00
|
|
|
#define Cdrskin_grab_abort_brokeN 1
|
2006-09-07 11:55:42 +00:00
|
|
|
#endif
|
2006-08-18 17:03:41 +00:00
|
|
|
|
2006-09-21 17:29:41 +00:00
|
|
|
/** Work around the fact that a freshly loaded tray with media reports
|
|
|
|
arbitrary media erasability in icculuc.org/burn */
|
2006-09-08 20:17:18 +00:00
|
|
|
#ifndef Cdrskin_is_erasable_on_load_does_worK
|
|
|
|
#define Cdrskin_is_erasable_on_load_is_brokeN 1
|
|
|
|
#endif
|
2006-08-18 17:03:41 +00:00
|
|
|
|
2006-09-21 17:29:41 +00:00
|
|
|
/** http://libburn.pykix.org/ticket/41 reports of big trouble without
|
|
|
|
padding any track to a full sector
|
|
|
|
*/
|
2006-09-15 17:48:30 +00:00
|
|
|
#define Cdrskin_all_tracks_with_sector_paD 1
|
|
|
|
|
|
|
|
|
2006-08-18 17:03:41 +00:00
|
|
|
/** A macro which is able to eat up a function call like printf() */
|
|
|
|
#ifdef Cdrskin_extra_leaN
|
|
|
|
#define ClN(x)
|
|
|
|
#else
|
|
|
|
#define ClN(x) x
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
2006-09-25 10:44:55 +00:00
|
|
|
/** Verbosity level for pacifying progress messages */
|
|
|
|
#define Cdrskin_verbose_progresS 1
|
|
|
|
|
|
|
|
/** Verbosity level for command recognition and execution logging */
|
|
|
|
#define Cdrskin_verbose_cmD 2
|
|
|
|
|
|
|
|
/** Verbosity level for reporting of debugging messages */
|
|
|
|
#define Cdrskin_verbose_debuG 3
|
|
|
|
|
|
|
|
|
2006-08-18 17:03:41 +00:00
|
|
|
#include <stdio.h>
|
|
|
|
#include <sys/types.h>
|
|
|
|
#include <sys/stat.h>
|
|
|
|
#include <fcntl.h>
|
|
|
|
#include <unistd.h>
|
|
|
|
#include <string.h>
|
|
|
|
#include <stdlib.h>
|
|
|
|
#include <errno.h>
|
|
|
|
#include <sys/time.h>
|
|
|
|
|
|
|
|
#include <libburn/libburn.h>
|
|
|
|
|
|
|
|
#include "cleanup.h"
|
|
|
|
|
|
|
|
|
|
|
|
/** The size of a string buffer for pathnames and similar texts */
|
|
|
|
#define Cdrskin_strleN 4096
|
|
|
|
|
|
|
|
/** The maximum length +1 of a drive address */
|
2006-09-21 18:57:01 +00:00
|
|
|
#ifndef Cdrskin_oldfashioned_api_usE
|
2006-08-24 13:53:37 +00:00
|
|
|
#define Cdrskin_adrleN BURN_DRIVE_ADR_LEN
|
|
|
|
#else
|
2006-08-18 17:03:41 +00:00
|
|
|
#define Cdrskin_adrleN 80
|
2006-08-24 13:53:37 +00:00
|
|
|
#endif
|
2006-08-18 17:03:41 +00:00
|
|
|
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/* Imported from scdbackup-0.8.5/src/cd_backup_planer.c */
|
|
|
|
|
|
|
|
/** Macro for creation of arrays of objects (or single objects) */
|
|
|
|
#define TSOB_FELD(typ,anz) (typ *) malloc((anz)*sizeof(typ));
|
|
|
|
|
|
|
|
|
|
|
|
/** Convert a text so that eventual characters special to the shell are
|
|
|
|
made literal. Note: this does not make a text terminal-safe !
|
|
|
|
@param in_text The text to be converted
|
|
|
|
@param out_text The buffer for the result.
|
|
|
|
It should have size >= strlen(in_text)*5+2
|
|
|
|
@param flag Unused yet
|
|
|
|
@return For convenience out_text is returned
|
|
|
|
*/
|
|
|
|
char *Text_shellsafe(char *in_text, char *out_text, int flag)
|
|
|
|
{
|
|
|
|
int l,i,w=0;
|
|
|
|
|
|
|
|
/* enclose everything by hard quotes */
|
|
|
|
l= strlen(in_text);
|
|
|
|
out_text[w++]= '\'';
|
|
|
|
for(i=0;i<l;i++){
|
|
|
|
if(in_text[i]=='\''){
|
|
|
|
/* escape hard quote within the text */
|
|
|
|
out_text[w++]= '\'';
|
|
|
|
out_text[w++]= '"';
|
|
|
|
out_text[w++]= '\'';
|
|
|
|
out_text[w++]= '"';
|
|
|
|
out_text[w++]= '\'';
|
|
|
|
} else {
|
|
|
|
out_text[w++]= in_text[i];
|
|
|
|
}
|
|
|
|
}
|
|
|
|
out_text[w++]= '\'';
|
|
|
|
out_text[w++]= 0;
|
|
|
|
return(out_text);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Convert a text into a number of type double and multiply it by unit code
|
|
|
|
[kmgtpe] (2^10 to 2^60) or [s] (2048). (Also accepts capital letters.)
|
|
|
|
@param text Input like "42", "2k", "3.14m" or "-1g"
|
|
|
|
@param flag Bitfield for control purposes:
|
|
|
|
bit0= return -1 rathern than 0 on failure
|
|
|
|
@return The derived double value
|
|
|
|
*/
|
|
|
|
double Scanf_io_size(char *text, int flag)
|
|
|
|
/*
|
|
|
|
bit0= default value -1 rather than 0
|
|
|
|
*/
|
|
|
|
{
|
|
|
|
int c;
|
|
|
|
double ret= 0.0;
|
|
|
|
|
|
|
|
if(flag&1)
|
|
|
|
ret= -1.0;
|
|
|
|
if(text[0]==0)
|
|
|
|
return(ret);
|
|
|
|
sscanf(text,"%lf",&ret);
|
|
|
|
c= text[strlen(text)-1];
|
|
|
|
if(c=='k' || c=='K') ret*= 1024.0;
|
|
|
|
if(c=='m' || c=='M') ret*= 1024.0*1024.0;
|
|
|
|
if(c=='g' || c=='G') ret*= 1024.0*1024.0*1024.0;
|
|
|
|
if(c=='t' || c=='T') ret*= 1024.0*1024.0*1024.0*1024.0;
|
|
|
|
if(c=='p' || c=='P') ret*= 1024.0*1024.0*1024.0*1024.0*1024.0;
|
|
|
|
if(c=='e' || c=='E') ret*= 1024.0*1024.0*1024.0*1024.0*1024.0*1024.0;
|
|
|
|
if(c=='s' || c=='S') ret*= 2048.0;
|
|
|
|
return(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Return a double representing seconds and microseconds since 1 Jan 1970 */
|
|
|
|
double Sfile_microtime(int flag)
|
|
|
|
{
|
|
|
|
struct timeval tv;
|
|
|
|
struct timezone tz;
|
|
|
|
gettimeofday(&tv,&tz);
|
|
|
|
return((double) (tv.tv_sec+1.0e-6*tv.tv_usec));
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef Cdrskin_extra_leaN
|
|
|
|
|
|
|
|
/** Read a line from fp and strip LF or CRLF */
|
|
|
|
char *Sfile_fgets(char *line, int maxl, FILE *fp)
|
|
|
|
{
|
|
|
|
int l;
|
|
|
|
char *ret;
|
|
|
|
ret= fgets(line,maxl,fp);
|
|
|
|
if(ret==NULL) return(NULL);
|
|
|
|
l= strlen(line);
|
|
|
|
if(l>0) if(line[l-1]=='\r') line[--l]= 0;
|
|
|
|
if(l>0) if(line[l-1]=='\n') line[--l]= 0;
|
|
|
|
if(l>0) if(line[l-1]=='\r') line[--l]= 0;
|
|
|
|
return(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Destroy a synthetic argument array */
|
|
|
|
int Sfile_destroy_argv(int *argc, char ***argv, int flag)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
|
|
|
|
if(*argc>0 && *argv!=NULL){
|
|
|
|
for(i=0;i<*argc;i++){
|
|
|
|
if((*argv)[i]!=NULL)
|
|
|
|
free((*argv)[i]);
|
|
|
|
}
|
|
|
|
free((char *) *argv);
|
|
|
|
}
|
|
|
|
*argc= 0;
|
|
|
|
*argv= NULL;
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Read a synthetic argument array from a list of files.
|
|
|
|
@param progname The content for argv[0]
|
|
|
|
@param filenames The paths of the filex from where to read
|
|
|
|
@param filenamecount The number of paths in filenames
|
|
|
|
@param argc Returns the number of read arguments (+1 for progname)
|
|
|
|
@param argv Returns the array of synthetic arguments
|
|
|
|
@param argidx Returns source file indice of argv[] items
|
|
|
|
@param arglno Returns source file line numbers of argv[] items
|
|
|
|
@param flag Bitfield for control purposes:
|
|
|
|
bit0= read progname as first argument from line
|
|
|
|
bit1= just release argument array argv and return
|
|
|
|
bit2= tolerate failure to open file
|
|
|
|
@return 1=ok , 0=cannot open file , -1=cannot create memory objects
|
|
|
|
*/
|
|
|
|
int Sfile_multi_read_argv(char *progname, char **filenames, int filename_count,
|
|
|
|
int *argc, char ***argv, int **argidx, int **arglno,
|
|
|
|
int flag)
|
|
|
|
{
|
|
|
|
int ret,i,pass,maxl=0,l,argcount=0,line_no;
|
|
|
|
char buf[Cdrskin_strleN];
|
|
|
|
FILE *fp= NULL;
|
|
|
|
|
|
|
|
Sfile_destroy_argv(argc,argv,0);
|
|
|
|
if(flag&2)
|
|
|
|
return(1);
|
|
|
|
if((*argidx)!=NULL)
|
|
|
|
free((char *) *argidx);
|
|
|
|
if((*arglno)!=NULL)
|
|
|
|
free((char *) *arglno);
|
|
|
|
*argidx= *arglno= NULL;
|
|
|
|
|
|
|
|
for(pass=0;pass<2;pass++) {
|
|
|
|
if(!(flag&1)){
|
|
|
|
argcount= 1;
|
|
|
|
if(pass==0)
|
|
|
|
maxl= strlen(progname)+1;
|
|
|
|
else {
|
|
|
|
(*argv)[0]= (char *) malloc(strlen(progname)+1);
|
|
|
|
if((*argv)[0]==NULL)
|
|
|
|
{ret= -1; goto ex;}
|
|
|
|
strcpy((*argv)[0],progname);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
argcount= 0;
|
|
|
|
if(pass==0)
|
|
|
|
maxl= 1;
|
|
|
|
}
|
|
|
|
for(i=0; i<filename_count;i++) {
|
|
|
|
if(strlen(filenames[i])==0)
|
|
|
|
continue;
|
|
|
|
fp= fopen(filenames[i],"rb");
|
|
|
|
if(fp==NULL) {
|
|
|
|
if(flag&4)
|
|
|
|
continue;
|
|
|
|
{ret= 0; goto ex;}
|
|
|
|
}
|
2006-09-27 07:47:35 +00:00
|
|
|
|
|
|
|
#ifdef Cdrskin_new_api_tesT
|
|
|
|
if(pass>0)
|
|
|
|
fprintf(stderr,"cdrskin: DEBUG : Reading arguments from file '%s'\n",
|
|
|
|
filenames[i]);
|
|
|
|
#endif
|
|
|
|
|
2006-08-18 17:03:41 +00:00
|
|
|
line_no= 0;
|
|
|
|
while(Sfile_fgets(buf,sizeof(buf)-1,fp)!=NULL) {
|
|
|
|
line_no++;
|
|
|
|
l= strlen(buf);
|
|
|
|
if(pass==0){
|
|
|
|
if(l>maxl)
|
|
|
|
maxl= l;
|
|
|
|
} else {
|
|
|
|
if(argcount >= *argc)
|
|
|
|
break;
|
|
|
|
(*argv)[argcount]= (char *) malloc(l+1);
|
|
|
|
if((*argv)[argcount]==NULL)
|
|
|
|
{ret= -1; goto ex;}
|
|
|
|
strcpy((*argv)[argcount],buf);
|
|
|
|
(*argidx)[argcount]= i;
|
|
|
|
(*arglno)[argcount]= line_no;
|
|
|
|
}
|
|
|
|
argcount++;
|
|
|
|
}
|
|
|
|
fclose(fp); fp= NULL;
|
|
|
|
}
|
|
|
|
if(pass==0){
|
|
|
|
*argc= argcount;
|
|
|
|
if(argcount>0) {
|
|
|
|
*argv= (char **) malloc(argcount*sizeof(char *));
|
|
|
|
*argidx= (int *) malloc(argcount*sizeof(int));
|
|
|
|
*arglno= (int *) malloc(argcount*sizeof(int));
|
|
|
|
if(*argv==NULL || *argidx==NULL || *arglno==NULL)
|
|
|
|
{ret= -1; goto ex;}
|
|
|
|
}
|
|
|
|
for(i=0;i<*argc;i++) {
|
|
|
|
(*argv)[i]= NULL;
|
|
|
|
(*argidx)[i]= -1;
|
|
|
|
(*arglno)[i]= -1;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
ret= 1;
|
|
|
|
ex:;
|
|
|
|
if(fp!=NULL)
|
|
|
|
fclose(fp);
|
|
|
|
return(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Combine environment variable HOME with given filename
|
|
|
|
@param filename Address relative to $HOME
|
|
|
|
@param fileadr Resulting combined address
|
|
|
|
@param fa_size Size of array fileadr
|
|
|
|
@param flag Unused yet
|
|
|
|
@return 1=ok , 0=no HOME variable , -1=result address too long
|
|
|
|
*/
|
|
|
|
int Sfile_home_adr_s(char *filename, char *fileadr, int fa_size, int flag)
|
|
|
|
{
|
|
|
|
char *home;
|
|
|
|
|
|
|
|
strcpy(fileadr,filename);
|
|
|
|
home= getenv("HOME");
|
|
|
|
if(home==NULL)
|
|
|
|
return(0);
|
|
|
|
if(strlen(home)+strlen(filename)+1>=fa_size)
|
|
|
|
return(-1);
|
|
|
|
strcpy(fileadr,home);
|
|
|
|
if(filename[0]!=0){
|
|
|
|
strcat(fileadr,"/");
|
|
|
|
strcat(fileadr,filename);
|
|
|
|
}
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#endif /* ! Cdrskin_extra_leaN */
|
|
|
|
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
/** Address translation table for users/applications which do not look
|
|
|
|
for the output of -scanbus but guess a Bus,Target,Lun on their own.
|
|
|
|
*/
|
|
|
|
|
|
|
|
/** The maximum number of entries in the address translation table */
|
|
|
|
#define Cdradrtrn_leN 256
|
|
|
|
|
|
|
|
/** The address prefix which will prevent translation */
|
|
|
|
#define Cdrskin_no_transl_prefiX "LITERAL_ADR:"
|
|
|
|
|
|
|
|
|
|
|
|
struct CdradrtrN {
|
|
|
|
char *from_address[Cdradrtrn_leN];
|
|
|
|
char *to_address[Cdradrtrn_leN];
|
|
|
|
int fill_counter;
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef Cdrskin_extra_leaN
|
|
|
|
|
|
|
|
/** Create a device address translator object */
|
|
|
|
int Cdradrtrn_new(struct CdradrtrN **trn, int flag)
|
|
|
|
{
|
|
|
|
struct CdradrtrN *o;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
(*trn)= o= TSOB_FELD(struct CdradrtrN,1);
|
|
|
|
if(o==NULL)
|
|
|
|
return(-1);
|
|
|
|
for(i= 0;i<Cdradrtrn_leN;i++) {
|
|
|
|
o->from_address[i]= NULL;
|
|
|
|
o->to_address[i]= NULL;
|
|
|
|
}
|
|
|
|
o->fill_counter= 0;
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Release from memory a device address translator object */
|
|
|
|
int Cdradrtrn_destroy(struct CdradrtrN **o, int flag)
|
|
|
|
{
|
|
|
|
int i;
|
|
|
|
struct CdradrtrN *trn;
|
|
|
|
|
|
|
|
trn= *o;
|
|
|
|
if(trn==NULL)
|
|
|
|
return(0);
|
|
|
|
for(i= 0;i<trn->fill_counter;i++) {
|
|
|
|
if(trn->from_address[i]!=NULL)
|
|
|
|
free(trn->from_address[i]);
|
|
|
|
if(trn->to_address[i]!=NULL)
|
|
|
|
free(trn->to_address[i]);
|
|
|
|
}
|
|
|
|
free((char *) trn);
|
|
|
|
*o= NULL;
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Add a translation pair to the table
|
|
|
|
@param trn The translator which shall learn
|
|
|
|
@param from The user side address
|
|
|
|
@param to The cdrskin side address
|
|
|
|
@param flag Bitfield for control purposes:
|
|
|
|
bit0= "from" contains from+to address, to[0] contains delimiter
|
|
|
|
*/
|
|
|
|
int Cdradrtrn_add(struct CdradrtrN *trn, char *from, char *to, int flag)
|
|
|
|
{
|
|
|
|
char buf[2*Cdrskin_adrleN+1],*from_pt,*to_pt;
|
|
|
|
int cnt;
|
|
|
|
|
|
|
|
cnt= trn->fill_counter;
|
|
|
|
if(cnt>=Cdradrtrn_leN)
|
|
|
|
return(-1);
|
|
|
|
if(flag&1) {
|
|
|
|
if(strlen(from)>=sizeof(buf))
|
|
|
|
return(0);
|
|
|
|
strcpy(buf,from);
|
|
|
|
to_pt= strchr(buf,to[0]);
|
|
|
|
if(to_pt==NULL)
|
|
|
|
return(0);
|
|
|
|
*(to_pt)= 0;
|
|
|
|
from_pt= buf;
|
|
|
|
to_pt++;
|
|
|
|
} else {
|
|
|
|
from_pt= from;
|
|
|
|
to_pt= to;
|
|
|
|
}
|
|
|
|
if(strlen(from)>=Cdrskin_adrleN || strlen(to)>=Cdrskin_adrleN)
|
|
|
|
return(0);
|
|
|
|
trn->from_address[cnt]= malloc(strlen(from_pt)+1);
|
|
|
|
trn->to_address[cnt]= malloc(strlen(to_pt)+1);
|
|
|
|
if(trn->from_address[cnt]==NULL ||
|
|
|
|
trn->to_address[cnt]==NULL)
|
|
|
|
return(-2);
|
|
|
|
strcpy(trn->from_address[cnt],from_pt);
|
|
|
|
strcpy(trn->to_address[cnt],to_pt);
|
|
|
|
trn->fill_counter++;
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Apply eventual device address translation
|
|
|
|
@param trn The translator
|
|
|
|
@param from The address from which to translate
|
|
|
|
@param driveno With backward translation only: The libburn drive number
|
|
|
|
@param to The result of the translation
|
|
|
|
@param flag Bitfield for control purposes:
|
|
|
|
bit0= translate backward
|
|
|
|
@return <=0 error, 1=no translation found, 2=translation found,
|
|
|
|
3=collision avoided
|
|
|
|
*/
|
|
|
|
int Cdradrtrn_translate(struct CdradrtrN *trn, char *from, int driveno,
|
|
|
|
char to[Cdrskin_adrleN], int flag)
|
|
|
|
{
|
|
|
|
int i,ret= 1;
|
|
|
|
char *adr;
|
|
|
|
|
|
|
|
to[0]= 0;
|
|
|
|
adr= from;
|
|
|
|
if(flag&1)
|
|
|
|
goto backward;
|
|
|
|
|
|
|
|
if(strncmp(adr,Cdrskin_no_transl_prefiX,
|
|
|
|
strlen(Cdrskin_no_transl_prefiX))==0) {
|
|
|
|
adr= adr+strlen(Cdrskin_no_transl_prefiX);
|
|
|
|
ret= 2;
|
|
|
|
} else {
|
|
|
|
for(i=0;i<trn->fill_counter;i++)
|
|
|
|
if(strcmp(adr,trn->from_address[i])==0)
|
|
|
|
break;
|
|
|
|
if(i<trn->fill_counter) {
|
|
|
|
adr= trn->to_address[i];
|
|
|
|
ret= 2;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
if(strlen(adr)>=Cdrskin_adrleN)
|
|
|
|
return(-1);
|
|
|
|
strcpy(to,adr);
|
|
|
|
return(ret);
|
|
|
|
|
|
|
|
backward:;
|
|
|
|
if(strlen(from)>=Cdrskin_adrleN)
|
|
|
|
sprintf(to,"%s%d",Cdrskin_no_transl_prefiX,driveno);
|
|
|
|
else
|
|
|
|
strcpy(to,from);
|
|
|
|
for(i=0;i<trn->fill_counter;i++)
|
|
|
|
if(strcmp(from,trn->to_address[i])==0 &&
|
|
|
|
strlen(trn->from_address[i])<Cdrskin_adrleN)
|
|
|
|
break;
|
|
|
|
if(i<trn->fill_counter) {
|
|
|
|
ret= 2;
|
|
|
|
strcpy(to,trn->from_address[i]);
|
|
|
|
} else {
|
|
|
|
for(i=0;i<trn->fill_counter;i++)
|
|
|
|
if(strcmp(from,trn->from_address[i])==0)
|
|
|
|
break;
|
|
|
|
if(i<trn->fill_counter)
|
|
|
|
if(strlen(from)+strlen(Cdrskin_no_transl_prefiX)<Cdrskin_adrleN) {
|
|
|
|
ret= 3;
|
|
|
|
sprintf(to,"%s%s",Cdrskin_no_transl_prefiX,from);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return(ret);
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif /* Cdrskin_extra_leaN */
|
|
|
|
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------- */
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef Cdrskin_extra_leaN
|
|
|
|
|
|
|
|
/* Program is to be linked with cdrfifo.c */
|
|
|
|
#include "cdrfifo.h"
|
|
|
|
|
|
|
|
#else /* ! Cdrskin_extra_leaN */
|
|
|
|
|
|
|
|
/* Dummy */
|
|
|
|
|
|
|
|
struct CdrfifO {
|
|
|
|
int dummy;
|
|
|
|
};
|
|
|
|
|
|
|
|
#endif /* Cdrskin_extra_leaN */
|
|
|
|
|
|
|
|
|
|
|
|
/* --------------------------------------------------------------------- */
|
|
|
|
|
2006-08-29 10:06:05 +00:00
|
|
|
/** cdrecord pads up to 600 kB in any case.
|
|
|
|
libburn yields blank result on tracks <~ 600 kB */
|
|
|
|
static double Cdrtrack_minimum_sizE= 600*1024;
|
|
|
|
|
2006-08-18 17:03:41 +00:00
|
|
|
|
|
|
|
/** This structure represents a track resp. a data source */
|
|
|
|
struct CdrtracK {
|
|
|
|
|
|
|
|
struct CdrskiN *boss;
|
|
|
|
int trackno;
|
|
|
|
|
|
|
|
char source_path[Cdrskin_strleN];
|
|
|
|
int source_fd;
|
2006-09-01 14:48:54 +00:00
|
|
|
int is_from_stdin;
|
2006-08-18 17:03:41 +00:00
|
|
|
double fixed_size;
|
|
|
|
double padding;
|
2006-09-02 09:44:38 +00:00
|
|
|
int set_by_padsize;
|
2006-09-12 20:12:17 +00:00
|
|
|
int sector_pad_up; /* enforce single sector padding */
|
2006-08-23 18:56:26 +00:00
|
|
|
int track_type;
|
2006-08-18 17:03:41 +00:00
|
|
|
|
|
|
|
/** Optional fifo between input fd and libburn. It uses a pipe(2) to transfer
|
|
|
|
data to libburn.
|
|
|
|
*/
|
|
|
|
int fifo_enabled;
|
|
|
|
/** The fifo object knows the real input fd and the fd[1] of the pipe. */
|
|
|
|
struct CdrfifO *fifo;
|
|
|
|
/** fd[0] of the fifo pipe. This is from where libburn reads its data. */
|
|
|
|
int fifo_outlet_fd;
|
|
|
|
int fifo_size;
|
|
|
|
int fifo_start_empty;
|
|
|
|
|
|
|
|
struct burn_track *libburn_track;
|
|
|
|
|
|
|
|
};
|
|
|
|
|
|
|
|
int Cdrtrack_destroy(struct CdrtracK **o, int flag);
|
|
|
|
|
|
|
|
|
|
|
|
/** Create a track resp. data source object.
|
|
|
|
@param track Returns the address of the new object.
|
|
|
|
@param boss The cdrskin control object (corresponds to session)
|
|
|
|
@param trackno The index in the cdrskin tracklist array (is not constant)
|
|
|
|
@param flag Bitfield for control purposes:
|
|
|
|
bit0= set fifo_start_empty to 1
|
2006-09-01 14:48:54 +00:00
|
|
|
bit1= track is originally stdin
|
2006-08-18 17:03:41 +00:00
|
|
|
*/
|
|
|
|
int Cdrtrack_new(struct CdrtracK **track, struct CdrskiN *boss,
|
|
|
|
int trackno, int flag)
|
|
|
|
{
|
|
|
|
struct CdrtracK *o;
|
|
|
|
int ret;
|
|
|
|
int Cdrskin_get_source(struct CdrskiN *skin, char *source_path,
|
2006-08-23 18:56:26 +00:00
|
|
|
double *fixed_size, double *padding,
|
2006-09-02 09:44:38 +00:00
|
|
|
int *set_by_padsize, int *track_type, int flag);
|
2006-08-18 17:03:41 +00:00
|
|
|
int Cdrskin_get_fifo_par(struct CdrskiN *skin, int *fifo_enabled,
|
|
|
|
int *fifo_size, int *fifo_start_empty, int flag);
|
|
|
|
|
|
|
|
(*track)= o= TSOB_FELD(struct CdrtracK,1);
|
|
|
|
if(o==NULL)
|
|
|
|
return(-1);
|
|
|
|
o->boss= boss;
|
|
|
|
o->trackno= trackno;
|
|
|
|
o->source_path[0]= 0;
|
|
|
|
o->source_fd= -1;
|
2006-09-01 14:48:54 +00:00
|
|
|
o->is_from_stdin= !!(flag&2);
|
2006-08-18 17:03:41 +00:00
|
|
|
o->fixed_size= 0.0;
|
|
|
|
o->padding= 0.0;
|
2006-09-02 09:44:38 +00:00
|
|
|
o->set_by_padsize= 0;
|
2006-09-15 17:48:30 +00:00
|
|
|
o->sector_pad_up= Cdrskin_all_tracks_with_sector_paD;
|
2006-08-24 19:23:09 +00:00
|
|
|
o->track_type= BURN_MODE1;
|
2006-08-18 17:03:41 +00:00
|
|
|
o->fifo_enabled= 0;
|
|
|
|
o->fifo= NULL;
|
|
|
|
o->fifo_outlet_fd= -1;
|
|
|
|
o->fifo_size= 0;
|
|
|
|
o->fifo_start_empty= 0;
|
|
|
|
o->libburn_track= NULL;
|
2006-08-23 18:56:26 +00:00
|
|
|
ret= Cdrskin_get_source(boss,o->source_path,&(o->fixed_size),&(o->padding),
|
2006-09-02 09:44:38 +00:00
|
|
|
&(o->set_by_padsize),&(o->track_type),0);
|
2006-08-18 17:03:41 +00:00
|
|
|
if(ret<=0)
|
|
|
|
goto failed;
|
|
|
|
|
|
|
|
#ifndef Cdrskin_extra_leaN
|
|
|
|
ret= Cdrskin_get_fifo_par(boss, &(o->fifo_enabled),&(o->fifo_size),
|
|
|
|
&(o->fifo_start_empty),0);
|
|
|
|
if(ret<=0)
|
|
|
|
goto failed;
|
|
|
|
#endif /* ! Cdrskin_extra_leaN */
|
|
|
|
|
|
|
|
if(flag&1)
|
|
|
|
o->fifo_start_empty= 1;
|
|
|
|
return(1);
|
|
|
|
failed:;
|
|
|
|
Cdrtrack_destroy(track,0);
|
|
|
|
return(-1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Release from memory a track object previously created by Cdrtrack_new() */
|
|
|
|
int Cdrtrack_destroy(struct CdrtracK **o, int flag)
|
|
|
|
{
|
|
|
|
struct CdrtracK *track;
|
|
|
|
|
|
|
|
track= *o;
|
|
|
|
if(track==NULL)
|
|
|
|
return(0);
|
|
|
|
|
|
|
|
#ifndef Cdrskin_extra_leaN
|
|
|
|
Cdrfifo_destroy(&(track->fifo),0);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
if(track->libburn_track!=NULL)
|
|
|
|
burn_track_free(track->libburn_track);
|
|
|
|
free((char *) track);
|
|
|
|
*o= NULL;
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Cdrtrack_get_size(struct CdrtracK *track, double *size, double *padding,
|
|
|
|
int flag)
|
|
|
|
{
|
|
|
|
*size= track->fixed_size;
|
|
|
|
*padding= track->padding;
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
int Cdrtrack_get_fifo(struct CdrtracK *track, struct CdrfifO **fifo, int flag)
|
|
|
|
{
|
|
|
|
*fifo= track->fifo;
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Deliver an open file descriptor corresponding to the source path of track.
|
|
|
|
@return <=0 error, 1 success
|
|
|
|
*/
|
|
|
|
int Cdrtrack_open_source_path(struct CdrtracK *track, int *fd, int flag)
|
|
|
|
{
|
|
|
|
if(track->source_path[0]=='-' && track->source_path[1]==0)
|
|
|
|
*fd= 0;
|
|
|
|
else if(track->source_path[0]=='#' &&
|
|
|
|
(track->source_path[1]>='0' && track->source_path[1]<='9'))
|
|
|
|
*fd= atoi(track->source_path+1);
|
|
|
|
else {
|
|
|
|
*fd= open(track->source_path,O_RDONLY);
|
|
|
|
if(*fd==-1) {
|
|
|
|
fprintf(stderr,"cdrskin: failed to open source address '%s'\n",
|
|
|
|
track->source_path);
|
|
|
|
fprintf(stderr,"cdrskin: errno=%d , \"%s\"\n",errno,
|
|
|
|
errno==0?"-no error code available-":strerror(errno));
|
|
|
|
} else {
|
|
|
|
if(track->fixed_size<=0) {
|
|
|
|
struct stat stbuf;
|
|
|
|
if(fstat(*fd,&stbuf)!=-1)
|
|
|
|
track->fixed_size= stbuf.st_size;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2006-08-31 09:26:44 +00:00
|
|
|
if(track->fixed_size<Cdrtrack_minimum_sizE && *fd>=0) {
|
2006-08-29 10:06:05 +00:00
|
|
|
fprintf(stderr,
|
|
|
|
"cdrskin: NOTE : Enforcing minimum track size of %.f bytes\n",
|
|
|
|
Cdrtrack_minimum_sizE);
|
|
|
|
track->fixed_size= Cdrtrack_minimum_sizE;
|
|
|
|
}
|
2006-08-18 17:03:41 +00:00
|
|
|
track->source_fd= *fd;
|
|
|
|
return(*fd>=0);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
#ifndef Cdrskin_extra_leaN
|
|
|
|
|
|
|
|
/** Install a fifo object between data source and libburn.
|
|
|
|
Its parameters are known to track.
|
|
|
|
@param outlet_fd Returns the filedescriptor of the fifo outlet.
|
|
|
|
@param previous_fifo Object address for chaining or follow-up attachment.
|
|
|
|
@param flag Bitfield for control purposes:
|
|
|
|
bit0= Debugging verbosity
|
|
|
|
bit1= Do not create and attach a new fifo
|
|
|
|
but attach new follow-up fd pair to previous_fifo
|
|
|
|
@return <=0 error, 1 success
|
|
|
|
*/
|
|
|
|
int Cdrtrack_attach_fifo(struct CdrtracK *track, int *outlet_fd,
|
|
|
|
struct CdrfifO *previous_fifo, int flag)
|
|
|
|
{
|
|
|
|
struct CdrfifO *ff;
|
|
|
|
int source_fd,pipe_fds[2],ret;
|
|
|
|
|
|
|
|
*outlet_fd= -1;
|
|
|
|
if(track->fifo_size<=0)
|
|
|
|
return(2);
|
|
|
|
ret= Cdrtrack_open_source_path(track,&source_fd,0);
|
|
|
|
if(ret<=0)
|
|
|
|
return(ret);
|
|
|
|
if(pipe(pipe_fds)==-1)
|
|
|
|
return(0);
|
|
|
|
|
|
|
|
Cdrfifo_destroy(&(track->fifo),0);
|
|
|
|
if(flag&2) {
|
|
|
|
ret= Cdrfifo_attach_follow_up_fds(previous_fifo,source_fd,pipe_fds[1],0);
|
|
|
|
if(ret<=0)
|
|
|
|
return(ret);
|
|
|
|
} else {
|
|
|
|
ret= Cdrfifo_new(&ff,source_fd,pipe_fds[1],2048,track->fifo_size,0);
|
|
|
|
if(ret<=0)
|
|
|
|
return(ret);
|
|
|
|
if(previous_fifo!=NULL)
|
|
|
|
Cdrfifo_attach_peer(previous_fifo,ff,0);
|
|
|
|
track->fifo= ff;
|
|
|
|
}
|
|
|
|
track->fifo_outlet_fd= pipe_fds[0];
|
|
|
|
if(flag&1)
|
|
|
|
printf(
|
|
|
|
"cdrskin_debug: track %d fifo replaced source_address '%s' by '#%d'\n",
|
|
|
|
track->trackno+1,track->source_path,track->fifo_outlet_fd);
|
|
|
|
sprintf(track->source_path,"#%d",track->fifo_outlet_fd);
|
|
|
|
track->source_fd= track->fifo_outlet_fd;
|
|
|
|
*outlet_fd= track->fifo_outlet_fd;
|
|
|
|
return(1);
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
/** Read data into the fifo until either it is full or the data source is
|
|
|
|
exhausted.
|
|
|
|
@return <=0 error, 1 success
|
|
|
|
*/
|
|
|
|
int Cdrtrack_fill_fifo(struct CdrtracK *track, int flag)
|
|
|
|
{
|
2006-09-01 14:48:54 +00:00
|
|