[Libburn] Re: How to pipe stdin to CD-RW ?

scdbackup at gmx.net scdbackup at gmx.net
Sun Dec 4 09:43:02 PST 2005


Hi,

it's quite a fun to build my own cdrecord.

I must say that the code and the concept of libburn
seem very accessible to me. 

Following are some notes which i collected meanwhile.

Let me hope that my reports and proposals are not
too obtrusive.
(I will review my changes and enhance them so that
they are ready to be included in libburn. I will
also make the proposed change of the data type for
source sizes. Then i will post a diff.)
Are there significant differences between the
tarball version and the CVS version ?


-----------------------------------------------------
The following call does not eject my HL-DT-ST DVDRAM GSA-4082B
(Linux 2.4.21-215-athlon, ide-scsi) :

  burn_drive_release(drive, 1);

Despite the manual saying :
"eject 	Nonzero to make the drive eject the disc in it."
The burn was successful, though.

My  drives[0].location  is "/dev/sg0".
Even root cannot eject /dev/sg0 on my system
  # ls -l /dev/sg0
  crw-rw-rw-    1 root     disk      21,   0 Sep 23  2003 /dev/sg0
  # eject /dev/sg0
  eject: unable to eject, last error: Operation not permitted

Ejectable is /dev/sr0 
  # ls -l /dev/sr0
  brw-rw----    1 thomas   floppy    11,   0 Sep 23  2003 /dev/sr0

If i knew a reliable method to derive "/dev/sr0" from "/dev/sg0" ...
Well, if its sg0 then it can hardly be anything else but sr0.
What what to think of sg3 ?


-----------------------------------------------------
The following call does not set speed to 4x.
  k_speed= 4*150;
  burn_drive_set_speed(drive,k_speed,k_speed);

The drive is capable of 10x, the media is a 4x-12x CD-RW .
Actual speed is about 1800 sectors per 2 second progress
line in RAW96R mode. That would be about 12x. Strange.

In SAO mode, speed seems to be 1200 sectors per 2 second.
That would be 8x . 
Where can i learn about read compatibility of the
various modes (like for ISO-9660 on MS-Windows) ?


-----------------------------------------------------
The following call returns confusing values with a 4x CD-RW
  ret= burn_drive_get_write_speed(drive);
  printf("  burn_drive_get_write_speed = %d\n",ret);
yields
  burn_drive_get_write_speed = 1764
and on second try
  burn_drive_get_write_speed = 4234
That would be about 28x.

  cdrecord dev=0,0,0 -v -atip :
    ...
    ATIP info from disk:
    Indicated writing power: 5
    Reference speed: 2
    Is not unrestricted
    Is erasable
    ATIP start of lead in:  -11597 (97:27/28)
    ATIP start of lead out: 336601 (74:50/01)
    1T speed low:  0 (reserved val  0) 1T speed high:  4
    2T speed low:  0 (reserved val  5) 2T speed high:  0 (reserved val 10)
    power mult factor: 5 6
    recommended erase/write power: 3
    A1 values: 02 5C B0
    A2 values: 5A DC 36
  Disk type:    Phase change
  Manuf. index: 20
  Manufacturer: Princo Corporation

The same i get with a used 52x CD-R (BURN_DISC_APPENDABLE)

  cdrecord dev=0,0,0 -v -atip :
  ATIP info from disk:
    Indicated writing power: 4
    Is not unrestricted
    Is not erasable
    Disk sub type: Medium Type A, low Beta category (A-) (2)
    ATIP start of lead in:  -12508 (97:15/17)
    ATIP start of lead out: 359845 (79:59/70)
  Disk type:    Short strategy type (Phthalocyanine or similar)
  Manuf. index: 22
  Manufacturer: Ritek Co.

and a blank 52x CD-R (BURN_DISC_BLANK)

  ATIP info from disk:
    Indicated writing power: 5
    Is not unrestricted
    Is not erasable
    Disk sub type: Medium Type B, low Beta category (B-) (4)
    ATIP start of lead in:  -12369 (97:17/06)
    ATIP start of lead out: 359849 (79:59/74)
  Disk type:    Short strategy type (Phthalocyanine or similar)
  Manuf. index: 69
  Manufacturer: Moser Baer India Limited

and a used 4x DVD+RW (announced as BURN_DISC_BLANK)

  book type:       DVD+RW, Version 2 (9.2)
  ...
  Manufacturer:    'RICOHJPN'
  Media type:      'W11'


-----------------------------------------------------
Shouldn't
  burn_write_opts_set_simulate(o, 1);
in test/burniso.c have prevented the burning ?
"sim 	If non-zero, the drive will perform a simulation instead of a burn"
My drive does burn.


-----------------------------------------------------
I am exploring the higher levels of the disk burn 
procedure within libburn in order to find a place
to implement user defined padding.

Do i get it right that function 
  burn_write_session
already would truncate surplus bytes from the source ?
        for (i = 0; i < sectors - tmp; i++) {
                sector_data(o, t, 0);

Do i get it right that any source input is done
via  src->read  which actually points to function 
 file_read  in file.c ?

Do i get it right that the data source has to
provide blocking input anyway ?
(I.e. that  src->read  has to deliver a full buffer
of size bytes unless EOF is encountered. If half
buffers are allowed, the following trick would
not work.)


If one would introduce new members into 

struct burn_source {
...
        /** Amount of bytes to virtually read after source's data */
        int bytes_to_pad;       
        /** Amount of bytes already appended after source's data */
        int padded_bytes;  
...
};

and implement a second reader function

int file_read_and_pad(struct burn_source *source, unsigned char *buffer,
                         int size)
{
        struct burn_source_file *fs = source->data;
        int ret;

        ret = read(fs->datafd, buffer, size);
        if(ret<0)
                return ret;
        for(; ret<size && source->padded_bytes<source->bytes_to_pad; ret++) {
                buffer[ret] = 0;
                source->padded_bytes++;
        }
        return ret;
}

one could cause padding by this new function :

/** Adds surplus size which will be padded with 0s if not filled by source */
void burn_source_add_padding(struct burn_source *src, int pad_size, int no_end)
{
        int size;
        int file_read_and_pad();

        src->fixed_size = burn_source_get_size(src) + pad_size;
        src->read = file_read_and_pad;
        if(no_end)
                src->bytes_to_pad = 0x7FFFFFFF; /* could need a larger type */
        else
                src->bytes_to_pad += pad_size;
        src->padded_bytes = 0;
}

This call would be made directly after  burn_file_source_new*() .

If input turns out to be oversized then padding would
become victim to truncation. The track size would not
overflow.

no_end is useful for the current write modes, since it
pads up the input stream to the originally scheduled size.
With a future TAO write mode which does not demand a
size in advance, no_end==0 will be necessary for learning
about the end of input.


Again, i tested this by an experimental implementation
in libburn. It seems to work.
My checkreader now gets about 300 kB extra bytes after
the checksum mark. Just like with cdrecord.


-----------------------------------------------------
I got the impression that it is a bad idea for the
the data source size variable to have type int.
As soon as libburn ever encounters media larger than
2 GB there will be the need to change to a different
type.
Since i just proposed API functions which expose
that type to the public, i hereby propose to change 
it to type off_t or to type double. 
The same should be done to struct burn_source and
function file_size (which currently needs a cast in
its return statement to be 64-bit safe, i think).

How is libburn positioned towards large files ?
Things like : -D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE 
It is said that the macros are described in  info libc
Found by google:
  http://www.gnu.org/software/libc/manual/html_node/Feature-Test-Macros.html
I once got my inspirations from :
  http://www.suse.de/~aj/linux_lfs.html


-----------------------------------------------------
The verbosity level 1 is quite unusable because it 
reports many times and very fast 
  logical unit is in the process of becoming ready


-----------------------------------------------------
There are two groups of messages printed by libburn
regardless of verbosity level :

ignored nwa: 0

ctladr|trno|indx|form|scms|  msf
------+----+----+----+----+--------
 4  1 | 00 | 00 | 01 | 00 |00:00:00
 4  1 | 01 | 00 | 10 | 00 |00:00:00
 4  1 | 01 | 01 | 10 | 00 |00:02:00
 4  1 | AA | 01 | 01 | 00 |11:08:00

There should be a way to disable them.


-----------------------------------------------------
It looks like i could need a pipe fed burn_source.
That would need another class of pseudo-addresses
besides "-".
Something like "#7" to attach file descriptor 7 to
burn_source would be nice.
Alternatively a new constructor which gets 4 arguments.

In file.c , burn_file_source_new3 :
        if (path[0]=='-' && path[1]==0)
                fd1 = 0;
+       else if (path[0]=='#')
+               fd1= atoi(path+1);
        else
                fd1 = open(path, O_RDONLY);

To be used like :
  pipe(filedes);
  sprintf(path,"#%d",filedes[0]);
  src = burn_file_source_new3(path,NULL,(int) fixed_size);
  ...
  while (burn_drive_get_status(drive, &p)) {
    ... check for drive status ...
    last_time= time(0);
    while(time(0)<last_time+2) {
      ... fill data into buffer ...
      write(filedes[1],buffer,count);
    }
  }

Would this loop be ok ?
Is there already a different way (without a burn_source)
to write self generated data onto CD ?

There are alternatives on base of dup2() but they would
poke deep and dirty into the runtime entrails of libburn.


-----------------------------------------------------
What to do if i find the media in state BURN_DISC_APPENDABLE
and want to blank it ?
Run a mini burn session on it and then try again ?


-----------------------------------------------------
About the current development status:


$ ls -l test/cdrskin.c
-rw-r--r--    1 thomas   thomas      28096 Dec  4 17:11 test/cdrskin.c


$ test/cdrskin --help
cdrskin 0.2.ts.0.0.1 : limited cdrecord compatibility wrapper for libburn

Usage: test/cdrskin [options] [source_address]
Burns preformatted data to CD-R or CD-RW via libburn.
Options:
 --drive <num>      chooses a drive number
 --verbose <level>  sets verbosity level of libburn
 --fixed_size <num> announces source bytes (needed with "-")
Some cdrecord compatible options are implemented for scdbackup.
See output of option -help rather than --help.
If the last argument is not a known option then it is used as
data source file. If it is "-" then stdin is used. In this
case the total byte count of the source must be announced via
tsize= or --fixed_size.
libburn  : http://icculus.org/burn
cdrecord : ftp://ftp.berlios.de/pub/cdrecord/
My respect to the authors of cdrecord and libburn.
scdbackup: http://scdbackup.webframe.org/main_eng.html


$ test/cdrskin -help     
cdrskin 0.2.ts.0.0.1 : limited cdrecord compatibility wrapper for libburn
Usage: test/cdrskin [options] [source_address]
(Note: This is not cdrecord. See start message on stdout. See --help)
Options:
        -version        print version information and exit
        dev=target      pseudo-SCSI target to use as CD-Recorder
        -v              increment libburn verbose level by one
        driveropts=opt  opt= one of {burnfree,noburnfree,help}
        -checkdrive     ignored yet
        -scanbus        scan the pseudo bus for drives and exit
        speed=#         set speed of drive
        blank=type      blank a CD-RW disc (see blank=help)
        fs=#            ignored yet
        -eject          eject the disk after doing the work (might be ignored)
        -atip           evaluate media, print "Is *erasable"
        -raw96r         Write disk in RAW/RAW96R mode
        -sao            Write disk in SAO mode.
        tsize=#         announces exact size of source data
        padsize=#       Amount of padding
        -data           ignored yet
        -pad            padsize=30k
        -nopad          Do not pad (default)
        -help           print this text to stderr and exit
If the last argument is not a known option then it is used as
data source file. If it is "-" then stdin is used. In this case
the total byte count of the source must be announced via tsize=#.
Different from cdrecord, padding of 0 or more bytes will ensure
that the announced tsize= is written. If the source delivers
surplus bytes, they will replace the padding 0s.

For getting a list of drives :

$ test/cdrskin -scanbus
cdrskin 0.2.ts.0.0.1 : limited cdrecord compatibility wrapper for libburn
cdrskin: initializing libburn...Success
cdrskin: scanning for devices...Done
Using libburn version '0.2.ts'.
pseudobus0:
        0,0,0     0) 'HL-DT-ST' 'DVDRAM GSA-4082B' '?' Removable CD-ROM


This is how i learn from cdrecord wether there is a CD-RW or CD-R.

$ test/cdrskin dev=0,0,0 -atip
cdrskin 0.2.ts.0.0.1 : limited cdrecord compatibility wrapper for libburn
cdrskin: initializing libburn...Success
cdrskin: scanning for devices...Done
cdrskin: active drive number : 0
cdrskin: will put out some -atip style line
cdrskin: pseudo-atip on drive 0
cdrskin: status 4 BURN_DISC_FULL "There is a disc with data on it in the drive"
cdrskin: burn_drive_get_write_speed = 4234
  Is erasable

CD-R would report "  Is not erasable".


Also working meanwhile :

Blanking :

$ test/cdrskin dev=0,0,0 blank=all -eject

$ test/cdrskin dev=0,0,0 blank=fast -eject


Burning SAO on the fly :

$ cat /dvdbuffer/fertig.afio | \
  test/cdrskin -v dev=0,0,0 speed=4 -sao driveropts=burnfree -eject \
               padsize=300k tsize=100m -

(speed does not really react on my settings, i fear)
(-eject will work only for /dev/sg0 == /dev/sr0 
 No idea yet what happens with ATAPI controled drives)
(It is not necessary to give the exact amount with tsize=.
 An upper limit is sufficient if padsize= is used.)


-----------------------------------------------------
And now the reason why i did this all :

The standard settings of my tool in respect to cdrecord are :

  $ scdbackup -show_configuration | grep CDRECORD
  SCDBACKUP_CDRECORD=cdrecord -v
  SCDBACKUP_CDRECORD_OPT=padsize=300k fs=8m -eject driveropts=burnfree -tao -data
  $ scdbackup -show_configuration | grep SCSI
  SCDBACKUP_SCSI_ADR=0,0,0 

I set the executable to write a full CD (Oh Lord, would
you throw TAO from heaven ? TIA.) and change option -tao
to -sao. The address can stay as it is.

  $ export SCDBACKUP_CDRECORD="/home/test/libburn-0.2.ts/test/cdrskin -v -v tsize=650m"
  $ export SCDBACKUP_CDRECORD_OPT="padsize=300k fs=8m -eject driveropts=burnfree -sao -data"

Tookie bo waba !

  $ scdbackup /=/home/FERTIG 
  scdbackup 0.8.5 en
  ...
  cd_backup_planer 0.8.5 : planning complete
  ########## part 1 of 1 (4 items   127.9m bytes)
  insert CD and press Enter

I do dare and press Enter. 
It works ! See mkisofs talking between libburn:
  ...
  S: 0/1 T: 0/1 L: -26: 4686/332950
  7.81% done, estimate finish Sun Dec  4 17:39:27 2005
  S: 0/1 T: 0/1 L: -26: 5895/332950
  ...
Well, it will last a bit longer than predicted.
520 MB of padding. (Oh Lord, would you ...)
  ...
  Total translation table size: 0
  Total rockridge attributes bytes: 267384
  Total directory bytes: 397312
  Path table size(bytes): 236
  Max brk space used 2272c4
  64043 extents written (125 MB)
  Note: blocklist file written : /u/thomas/blocklist_dir/cd_1_1_A51204.173931_131160064
  Note: cd_backup_planer added 32313 bytes of checksum padding
  S: 0/1 T: 0/1 L: -26: 64733/332950
  ...
The fact that my speed setting is 8 and it runs with 1.2 MB/s
is a miraculous coincidence. It will only work as long as i
believe in it and do not change anything. :)) 
  ...
  S: 0/1 T: 0/1 L: -26: 332950/332950
  S: 0/1 T: 0/1 L: 0: 0/0

  cdrskin: burning done
  cdrskin: trying to eject media
  ########## parts in total : 1
  backup script ended normally

Shall i believe that ?

  $ scdbackup_verify -auto
  scdbackup_verify 0.8.5 en
  ...
  Found matching record :
  1_1 A51204.173931 131160064 90a782b8a0864da510128725967cba6f
  Note: Checksum tag found by scanning confirms match.
  ...
  Note: read 550721536 surplus bytes
  OK.  Matching Record found . Passender Record gefunden .

The backup log says yes. The checksum tag on media says yes.
I believe it. It works for me.


Of course this will need a lot more of testing.

But it works right now !

-----------------------------------------------------


Have a nice day :)

Thomas



More information about the libburn mailing list