Compare commits
99 Commits
ZeroThreeF
...
ZeroThreeE
Author | SHA1 | Date | |
---|---|---|---|
0d3a31e3f0 | |||
205d5fed7d | |||
19c3d448a8 | |||
89762d91b4 | |||
a6acdc64cc | |||
7d23984220 | |||
aba535d700 | |||
203f158f5b | |||
e274c90f9d | |||
bf25c6edc8 | |||
2c467c8378 | |||
bdadae6ba5 | |||
1087d402f2 | |||
dc97c0d0df | |||
8b8afdd59b | |||
4dd8f098ac | |||
16b6e1905a | |||
22d1d56ebd | |||
0217702b8c | |||
81d68aeb83 | |||
0e23721f2d | |||
3a771b3da2 | |||
bacb815ecc | |||
f34d9efdb2 | |||
8efb863d5d | |||
d7ca1dd333 | |||
ddc2745495 | |||
12c4c73535 | |||
3326fcdb2d | |||
fba8eaef80 | |||
15a70555b2 | |||
83e196d69f | |||
c86f5d7cde | |||
8d7d177ce3 | |||
cd7b4e6de4 | |||
79adcb520b | |||
41f2a40a58 | |||
9b663f15d9 | |||
ed9d3e2545 | |||
ba7cd6d66e | |||
660bf40a3c | |||
25ba84a7e2 | |||
6566771834 | |||
2d2a2f8c1b | |||
329f266cea | |||
dce1ba57f3 | |||
d3f08d4f96 | |||
ddb63509af | |||
96098b3f2d | |||
256139c9d6 | |||
fd5b681bc6 | |||
2a38890c5f | |||
2ec2a34f51 | |||
10e320911a | |||
9699880581 | |||
13b9f910e1 | |||
acaba76cda | |||
927a820aec | |||
3b9f66a765 | |||
5d2ad006a4 | |||
aa03717f24 | |||
ab5f39b8bb | |||
e1b8edb437 | |||
a78e6f9b29 | |||
047f9c75f5 | |||
159715ebaa | |||
f617567e03 | |||
10a7a9d5e8 | |||
76ed9570c9 | |||
4bc8e4caea | |||
1a054b54c9 | |||
76a9fa4fa2 | |||
4c85686aad | |||
a686340407 | |||
16c7cf1889 | |||
15b33422d0 | |||
649f67697a | |||
125e28160d | |||
eb860ee4b7 | |||
a8c69206fe | |||
26745b4064 | |||
962f68b1d6 | |||
cc5560fc86 | |||
5d65697697 | |||
749d12591e | |||
98f0dab87e | |||
17c87b78a6 | |||
ecbe1c0f39 | |||
9507587652 | |||
dba40c756b | |||
fd9e5dc935 | |||
2816d8b569 | |||
64233b0ccc | |||
9e1b3719d6 | |||
6086b59301 | |||
c345426299 | |||
05216162ef | |||
13e2b23ace | |||
820f0924f9 |
@ -101,9 +101,9 @@ test_structest_CPPFLAGS = -Ilibburn
|
|||||||
test_structest_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
|
test_structest_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
|
||||||
test_structest_SOURCES = test/structest.c
|
test_structest_SOURCES = test/structest.c
|
||||||
|
|
||||||
## cdrskin construction site - ts A60816 - A70312
|
## cdrskin construction site - ts A60816 - A70720
|
||||||
cdrskin_cdrskin_CPPFLAGS = -Ilibburn
|
cdrskin_cdrskin_CPPFLAGS = -Ilibburn
|
||||||
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_0_3_4
|
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_0_3_8
|
||||||
cdrskin_cdrskin_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
|
cdrskin_cdrskin_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
|
||||||
cdrskin_cdrskin_SOURCES = cdrskin/cdrskin.c cdrskin/cdrfifo.c cdrskin/cdrfifo.h cdrskin/cdrskin_timestamp.h
|
cdrskin_cdrskin_SOURCES = cdrskin/cdrskin.c cdrskin/cdrfifo.c cdrskin/cdrfifo.h cdrskin/cdrskin_timestamp.h
|
||||||
##
|
##
|
||||||
|
12
README
12
README
@ -127,7 +127,7 @@ Project history as far as known to me:
|
|||||||
It has meanwhile moved to use vanilla libburn.pykix.org , though.
|
It has meanwhile moved to use vanilla libburn.pykix.org , though.
|
||||||
Version 0.1.4 constitutes the first release of this kind.
|
Version 0.1.4 constitutes the first release of this kind.
|
||||||
|
|
||||||
- In Juli 2006 our team mate Mario Danic announced a revival of libburn
|
- In July 2006 our team mate Mario Danic announced a revival of libburn
|
||||||
which by about nearly everybody else was perceived as unfriendly fork.
|
which by about nearly everybody else was perceived as unfriendly fork.
|
||||||
Derek Foreman four days later posted a message which expressed his
|
Derek Foreman four days later posted a message which expressed his
|
||||||
discontent.
|
discontent.
|
||||||
@ -197,13 +197,19 @@ Project history as far as known to me:
|
|||||||
DVD media. Code for double layer DVD+/-R is implemented but awaits a tester
|
DVD media. Code for double layer DVD+/-R is implemented but awaits a tester
|
||||||
yet.
|
yet.
|
||||||
|
|
||||||
|
- 23th April 2007 version 0.3.6 follows the unanimous opinion of Linux kernel
|
||||||
|
people that one should not use /dev/sg on kernel 2.6.
|
||||||
|
|
||||||
|
- 31st July 2007 version 0.3.8 marks the first anniversary of libburn revival.
|
||||||
|
We look back on improved stability, a substantially extended list of media
|
||||||
|
and write modes, and better protection against typical user mishaps.
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
This program is free software; you can redistribute it and/or modify
|
This program is free software; you can redistribute it and/or modify
|
||||||
it under the terms of the GNU General Public License as published by
|
it under the terms of the GNU General Public License as published by
|
||||||
the Free Software Foundation; either version 2 of the License, or
|
the Free Software Foundation. To be exact: version 2 of that License.
|
||||||
(at your option) any later version.
|
|
||||||
|
|
||||||
This program is distributed in the hope that it will be useful,
|
This program is distributed in the hope that it will be useful,
|
||||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
@ -26,12 +26,12 @@ following possible.
|
|||||||
cdrskin. By Thomas Schmitt <scdbackup@gmx.net>
|
cdrskin. By Thomas Schmitt <scdbackup@gmx.net>
|
||||||
Integrated sub project of libburnia.pykix.org but also published via:
|
Integrated sub project of libburnia.pykix.org but also published via:
|
||||||
http://scdbackup.sourceforge.net/cdrskin_eng.html
|
http://scdbackup.sourceforge.net/cdrskin_eng.html
|
||||||
http://scdbackup.sourceforge.net/cdrskin-0.3.4.pl00.tar.gz
|
http://scdbackup.sourceforge.net/cdrskin-0.3.8.tar.gz
|
||||||
Copyright (C) 2006-2007 Thomas Schmitt
|
Copyright (C) 2006-2007 Thomas Schmitt
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
|
|
||||||
On top of libburn there is implemented cdrskin 0.3.4, a limited cdrecord
|
On top of libburn there is implemented cdrskin 0.3.8, a limited cdrecord
|
||||||
compatibility wrapper which allows to use some libburn features from
|
compatibility wrapper which allows to use some libburn features from
|
||||||
the command line.
|
the command line.
|
||||||
Interested users of cdrecord are invited to participate in the development
|
Interested users of cdrecord are invited to participate in the development
|
||||||
@ -59,16 +59,16 @@ systems, including 64 bit systems. (Further reports are welcome.)
|
|||||||
|
|
||||||
Compilation, First Glimpse, Installation
|
Compilation, First Glimpse, Installation
|
||||||
|
|
||||||
Obtain cdrskin-0.3.4.pl00.tar.gz, take it to a directory of your choice and do:
|
Obtain cdrskin-0.3.8.tar.gz, take it to a directory of your choice and do:
|
||||||
|
|
||||||
tar xzf cdrskin-0.3.4.pl00.tar.gz
|
tar xzf cdrskin-0.3.8.tar.gz
|
||||||
cd cdrskin-0.3.4
|
cd cdrskin-0.3.8
|
||||||
|
|
||||||
Or obtain a libburnia.pykix.org SVN snapshot,
|
Or obtain a libburnia.pykix.org SVN snapshot,
|
||||||
go into the toplevel directory of the snapshot (e.g. cd libburn_pykix ),
|
go into the toplevel directory of the snapshot (e.g. cd libburn_pykix ),
|
||||||
and execute the autotools script ./bootstrap . Use autools version >= 1.7 .
|
and execute the autotools script ./bootstrap . Use autools version >= 1.7 .
|
||||||
|
|
||||||
Within that toplevel directory of either cdrskin-0.3.4 or libburn then execute:
|
Within that toplevel directory of either cdrskin-0.3.8 or libburn then execute:
|
||||||
|
|
||||||
./configure
|
./configure
|
||||||
make
|
make
|
||||||
@ -126,16 +126,16 @@ The superuser should be able to see any usable drive and then set the
|
|||||||
permissions as needed. If this hangs then there is a drive with
|
permissions as needed. If this hangs then there is a drive with
|
||||||
unexpected problems (locked, busy, broken, whatever). You might have to
|
unexpected problems (locked, busy, broken, whatever). You might have to
|
||||||
guess the address of your (non-broken) burner by other means, then.
|
guess the address of your (non-broken) burner by other means, then.
|
||||||
On Linux 2.4 this would be some /dev/sgN and on 2.6. some /dev/hdX.
|
On Linux 2.4 this would be some /dev/sgN and on 2.6. some /dev/srM or /dev/hdX.
|
||||||
|
|
||||||
The output of cdrskin --devices might look like
|
The output of cdrskin --devices might look like
|
||||||
|
|
||||||
0 dev='/dev/sg0' rwrwr- : '_NEC' 'DVD_RW ND-4570A'
|
0 dev='/dev/sr0' rwrwr- : '_NEC' 'DVD_RW ND-4570A'
|
||||||
1 dev='/dev/sg1' rwrw-- : 'HL-DT-ST' 'DVDRAM GSA-4082B'
|
1 dev='/dev/sr1' rwrw-- : 'HL-DT-ST' 'DVDRAM GSA-4082B'
|
||||||
|
|
||||||
So full and insecure enabling of both for everybody would look like
|
So full and insecure enabling of both for everybody would look like
|
||||||
|
|
||||||
chmod a+rw /dev/sg0 /dev/sg1
|
chmod a+rw /dev/sr0 /dev/sr1
|
||||||
|
|
||||||
I strongly discourage to run cdrskin with setuid root or via sudo !
|
I strongly discourage to run cdrskin with setuid root or via sudo !
|
||||||
It is not checked for the necessary degree of hacker safety.
|
It is not checked for the necessary degree of hacker safety.
|
||||||
@ -152,7 +152,7 @@ Get an overview of cdrecord style addresses of available devices
|
|||||||
cdrskin --devices
|
cdrskin --devices
|
||||||
|
|
||||||
Adresses reported with dev=ATA need prefix "ATA:". Address examples:
|
Adresses reported with dev=ATA need prefix "ATA:". Address examples:
|
||||||
dev=0,1,0 dev=ATA:1,0,0 dev=/dev/sg1 dev=/dev/hdc
|
dev=0,1,0 dev=ATA:1,0,0 dev=/dev/sg1 dev=/dev/hdc dev=/dev/sr0
|
||||||
See also "Drive Addressing" below.
|
See also "Drive Addressing" below.
|
||||||
|
|
||||||
Obtain some info about the drive
|
Obtain some info about the drive
|
||||||
@ -210,7 +210,7 @@ cdrskin -scanbus (and hopefully as listed with cdrecord -scanbus) :
|
|||||||
|
|
||||||
or a device file address as listed by --devices with an accessible drive :
|
or a device file address as listed by --devices with an accessible drive :
|
||||||
|
|
||||||
export SCDBACKUP_SCSI_ADR="/dev/sg1"
|
export SCDBACKUP_SCSI_ADR="/dev/sr1"
|
||||||
|
|
||||||
Set usage of cdrskin with appropriate options rather than cdrecord :
|
Set usage of cdrskin with appropriate options rather than cdrecord :
|
||||||
|
|
||||||
@ -272,8 +272,8 @@ the meaning of the components. A cdrecord-style address for cdrskin
|
|||||||
can be interpreted in two different modes.
|
can be interpreted in two different modes.
|
||||||
|
|
||||||
Standard mode tries to be compatible to original cdrecord. This should be true
|
Standard mode tries to be compatible to original cdrecord. This should be true
|
||||||
with (emulated) SCSI where the /dev/sgN with is looked up with matching
|
with (emulated) SCSI where the device file /dev/s[rg]N with is looked up with
|
||||||
scsibus,target,lun as given by the operating system.
|
matching scsibus,target,lun as given by the operating system.
|
||||||
With dev=ATA: or dev=ATAPI: the translation to /dev/hdX is purely literal
|
With dev=ATA: or dev=ATAPI: the translation to /dev/hdX is purely literal
|
||||||
but matches the cdrecord addresses on all systems tested so far:
|
but matches the cdrecord addresses on all systems tested so far:
|
||||||
X = 'a' + 2 * scsibus + target
|
X = 'a' + 2 * scsibus + target
|
||||||
@ -293,8 +293,8 @@ Component "scsibus" indicates the translation method. Defined busses are:
|
|||||||
1 associated to device file /dev/sgN , target chooses N
|
1 associated to device file /dev/sgN , target chooses N
|
||||||
2 associated to device file /dev/hdX , target 0='a', 1='b' ..., 25='z'
|
2 associated to device file /dev/hdX , target 0='a', 1='b' ..., 25='z'
|
||||||
|
|
||||||
So "1,1,0" is /dev/sg1, "2,3,0" is /dev/hdd, "0,2,0" is libburn drive #2 at
|
So "1,1,0" is /dev/sg1 (resp. its /dev/sr*), "2,3,0" is /dev/hdd,
|
||||||
some unspecified device file.
|
"0,2,0" is libburn drive #2 at some unspecified device file.
|
||||||
This scheme shall help to keep cdrecord-style addresses stable and exchangeable
|
This scheme shall help to keep cdrecord-style addresses stable and exchangeable
|
||||||
between users without excluding drives with unexpected device addresses.
|
between users without excluding drives with unexpected device addresses.
|
||||||
The numbering on bus 0 is prone to arbitrary changes caused by changes in
|
The numbering on bus 0 is prone to arbitrary changes caused by changes in
|
||||||
@ -314,12 +314,12 @@ Old frontends which do not know dev=ATA or dev=ATAPI and which do ask their
|
|||||||
|
|
||||||
To direct any remaining stubborn callers to the appropriate drives, cdrskin
|
To direct any remaining stubborn callers to the appropriate drives, cdrskin
|
||||||
allows to define device address aliases. Like
|
allows to define device address aliases. Like
|
||||||
cdrskin dev_translation=+1,0,0+/dev/sg1 \
|
cdrskin dev_translation=+1,0,0+/dev/sr1 \
|
||||||
dev_translation=+ATA:1,0,0+/dev/sg1 \
|
dev_translation=+ATA:1,0,0+/dev/sr1 \
|
||||||
dev_translation=-"cd+dvd"-0,1,0 \
|
dev_translation=-"cd+dvd"-0,1,0 \
|
||||||
...
|
...
|
||||||
Any of the addresses dev=1,0,0, dev=ATA:1,0,0, dev=cd+dvd will be mapped to
|
Any of the addresses dev=1,0,0, dev=ATA:1,0,0, dev=cd+dvd will be mapped to
|
||||||
/dev/sg1 resp. to 0,1,0.
|
/dev/sr1 resp. to 0,1,0.
|
||||||
The first character after "dev_translation=" defines the character which
|
The first character after "dev_translation=" defines the character which
|
||||||
separates the two parts of the translation pair. (Above: "+" and "-".)
|
separates the two parts of the translation pair. (Above: "+" and "-".)
|
||||||
|
|
||||||
@ -331,7 +331,7 @@ and to make them default in menu
|
|||||||
A suitable setting for "cdrecord" in menu
|
A suitable setting for "cdrecord" in menu
|
||||||
Settings:Configure K3b...:Programs:User Parameters
|
Settings:Configure K3b...:Programs:User Parameters
|
||||||
would then probably be
|
would then probably be
|
||||||
-v dev_translation=+1,0,0+/dev/sg1
|
-v dev_translation=+1,0,0+/dev/sr1
|
||||||
You will learn from button "Show Debugging Output" after a failed burn run
|
You will learn from button "Show Debugging Output" after a failed burn run
|
||||||
what cdrecord command was used with what address "dev=...". This address "..."
|
what cdrecord command was used with what address "dev=...". This address "..."
|
||||||
will be the right one to replace "1,0,0" in above example.
|
will be the right one to replace "1,0,0" in above example.
|
||||||
@ -402,7 +402,7 @@ most recent session. For example put an ISO filesystem at address 1 GB:
|
|||||||
cdrskin dev=/dev/sr0 -v fs=32m -eject speed=4 write_start_address=524288s -
|
cdrskin dev=/dev/sr0 -v fs=32m -eject speed=4 write_start_address=524288s -
|
||||||
The superuser may then do:
|
The superuser may then do:
|
||||||
mount -t iso9660 -o ro,sbsector=524288 /dev/sr0 /mnt
|
mount -t iso9660 -o ro,sbsector=524288 /dev/sr0 /mnt
|
||||||
Note: On my linux-2.4.21-215 mount works only with sbsector <= 337920 (660 MB).
|
Note: On my linux-2.4.21-215 mount works only with sbsector <= 337920 (660 MiB)
|
||||||
To extend a filesystem already existing at address 0
|
To extend a filesystem already existing at address 0
|
||||||
mkisofs -C 0,524288 -M /dev/sr0 ... | cdrskin dev=/dev/sr0 ...
|
mkisofs -C 0,524288 -M /dev/sr0 ... | cdrskin dev=/dev/sr0 ...
|
||||||
Record the number 524288 for usage as first number with -C at the next
|
Record the number 524288 for usage as first number with -C at the next
|
||||||
@ -447,7 +447,7 @@ too on blanking by cdrecord, dvd+rw-format or cdrskin. Perils of DVD-RW.
|
|||||||
There are three DVD-RW formatting variants with cdrskin currently:
|
There are three DVD-RW formatting variants with cdrskin currently:
|
||||||
|
|
||||||
blank=format_overwrite uses "DVD-RW Quick" formatting (MMC-type 15h)
|
blank=format_overwrite uses "DVD-RW Quick" formatting (MMC-type 15h)
|
||||||
and writes a first session of 128 MB. This leads to media which are expandable
|
and writes a first session of 128 MiB. This leads to media which are expandable
|
||||||
and random addressable by cdrskin.
|
and random addressable by cdrskin.
|
||||||
|
|
||||||
blank=format_overwrite_quickest uses "DVD-RW Quick" formatting (type 15h) too,
|
blank=format_overwrite_quickest uses "DVD-RW Quick" formatting (type 15h) too,
|
||||||
|
@ -38,7 +38,7 @@ original="./libburn_svn_release.tgz"
|
|||||||
# My changes are in $changes , mainly in $changes/cdrskin
|
# My changes are in $changes , mainly in $changes/cdrskin
|
||||||
changes="./libburn-release"
|
changes="./libburn-release"
|
||||||
|
|
||||||
skin_release="0.3.4"
|
skin_release="0.3.8"
|
||||||
patch_level=".pl00"
|
patch_level=".pl00"
|
||||||
skin_rev="$skin_release""$patch_level"
|
skin_rev="$skin_release""$patch_level"
|
||||||
|
|
||||||
@ -114,7 +114,8 @@ then
|
|||||||
fi
|
fi
|
||||||
cp -a "$cdrskin_dir" "$cdrskin_target"
|
cp -a "$cdrskin_dir" "$cdrskin_target"
|
||||||
|
|
||||||
# Remove copied binaries
|
# Remove copied vim.swp and binaries
|
||||||
|
rm "$cdrskin_target"/.*.swp
|
||||||
rm "$cdrskin_target"/*.o
|
rm "$cdrskin_target"/*.o
|
||||||
rm "$cdrskin_target"/cdrfifo
|
rm "$cdrskin_target"/cdrfifo
|
||||||
rm "$cdrskin_target"/cdrskin
|
rm "$cdrskin_target"/cdrskin
|
||||||
@ -137,7 +138,7 @@ do
|
|||||||
done
|
done
|
||||||
|
|
||||||
# Remove GIFs of cdrskin_eng.html
|
# Remove GIFs of cdrskin_eng.html
|
||||||
rm "$cdrskin_target"/doener_*.gif
|
rm "$cdrskin_target"/doener_*.gif "$cdrskin_target"/doener_*.png
|
||||||
|
|
||||||
# Remove automatically generated HTML man page
|
# Remove automatically generated HTML man page
|
||||||
rm "$cdrskin_target"/man_1_cdrskin.html
|
rm "$cdrskin_target"/man_1_cdrskin.html
|
||||||
@ -192,6 +193,18 @@ do
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Repair non-portable shell code output of ./bootstrap
|
||||||
|
(
|
||||||
|
cd "$compile_dir" || exit 1
|
||||||
|
sed -e 's/^for ac_header in$/test -z 1 \&\& for ac_header in dummy/' \
|
||||||
|
< ./configure > ./configure-repaired
|
||||||
|
if test "$?" = 0
|
||||||
|
then
|
||||||
|
echo "$0: Empty 'for ac_header in' found in configure." >&2
|
||||||
|
fi
|
||||||
|
mv ./configure-repaired ./configure
|
||||||
|
chmod a+rx,go-w,u+w ./configure
|
||||||
|
)
|
||||||
|
|
||||||
# Pack it up to the new libburn+cdrskin-tarball
|
# Pack it up to the new libburn+cdrskin-tarball
|
||||||
tar czf "$cdrskin_tarball" "$target"
|
tar czf "$cdrskin_tarball" "$target"
|
@ -38,7 +38,7 @@ original="./libburn_svn.tgz"
|
|||||||
# My changes are in $changes , mainly in $changes/cdrskin
|
# My changes are in $changes , mainly in $changes/cdrskin
|
||||||
changes="./libburn-develop"
|
changes="./libburn-develop"
|
||||||
|
|
||||||
skin_release="0.3.5"
|
skin_release="0.3.9"
|
||||||
patch_level=""
|
patch_level=""
|
||||||
skin_rev="$skin_release""$patch_level"
|
skin_rev="$skin_release""$patch_level"
|
||||||
|
|
||||||
@ -114,7 +114,8 @@ then
|
|||||||
fi
|
fi
|
||||||
cp -a "$cdrskin_dir" "$cdrskin_target"
|
cp -a "$cdrskin_dir" "$cdrskin_target"
|
||||||
|
|
||||||
# Remove copied binaries
|
# Remove copied vim.swp and binaries
|
||||||
|
rm "$cdrskin_target"/.*.swp
|
||||||
rm "$cdrskin_target"/*.o
|
rm "$cdrskin_target"/*.o
|
||||||
rm "$cdrskin_target"/cdrfifo
|
rm "$cdrskin_target"/cdrfifo
|
||||||
rm "$cdrskin_target"/cdrskin
|
rm "$cdrskin_target"/cdrskin
|
||||||
@ -137,7 +138,7 @@ do
|
|||||||
done
|
done
|
||||||
|
|
||||||
# Remove GIFs of cdrskin_eng.html
|
# Remove GIFs of cdrskin_eng.html
|
||||||
rm "$cdrskin_target"/doener_*.gif
|
rm "$cdrskin_target"/doener_*.gif "$cdrskin_target"/doener_*.png
|
||||||
|
|
||||||
# Remove automatically generated HTML man page
|
# Remove automatically generated HTML man page
|
||||||
rm "$cdrskin_target"/man_1_cdrskin.html
|
rm "$cdrskin_target"/man_1_cdrskin.html
|
||||||
@ -192,6 +193,19 @@ do
|
|||||||
fi
|
fi
|
||||||
done
|
done
|
||||||
|
|
||||||
|
# Repair non-portable shell code output of ./bootstrap
|
||||||
|
(
|
||||||
|
cd "$compile_dir" || exit 1
|
||||||
|
sed -e 's/^for ac_header in$/test -z 1 \&\& for ac_header in dummy/' \
|
||||||
|
< ./configure > ./configure-repaired
|
||||||
|
if test "$?" = 0
|
||||||
|
then
|
||||||
|
echo "$0: Empty 'for ac_header in' found in configure." >&2
|
||||||
|
fi
|
||||||
|
mv ./configure-repaired ./configure
|
||||||
|
chmod a+rx,go-w,u+w ./configure
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
# Pack it up to the new libburn+cdrskin-tarball
|
# Pack it up to the new libburn+cdrskin-tarball
|
||||||
tar czf "$cdrskin_tarball" "$target"
|
tar czf "$cdrskin_tarball" "$target"
|
||||||
@ -201,11 +215,11 @@ tar czf "$cdrskin_tarball" "$target"
|
|||||||
cd "$compile_dir" || exit 1
|
cd "$compile_dir" || exit 1
|
||||||
./configure
|
./configure
|
||||||
make
|
make
|
||||||
"$compile_cmd" -O2 -do_strip
|
"$compile_cmd" -libburn_svn -O2 -do_strip
|
||||||
cp "$compile_result" "../$bintarget_dynamic"
|
cp "$compile_result" "../$bintarget_dynamic"
|
||||||
if test -n "$compile_static_opts"
|
if test -n "$compile_static_opts"
|
||||||
then
|
then
|
||||||
"$compile_cmd" $compile_static_opts -O2 -do_strip
|
"$compile_cmd" $compile_static_opts -libburn_svn -O2 -do_strip
|
||||||
cp "$compile_result" "../$bintarget_static"
|
cp "$compile_result" "../$bintarget_static"
|
||||||
fi
|
fi
|
||||||
"$man_to_html_cmd"
|
"$man_to_html_cmd"
|
@ -77,6 +77,8 @@ struct CdrfifO {
|
|||||||
double empty_counter;
|
double empty_counter;
|
||||||
double full_counter;
|
double full_counter;
|
||||||
|
|
||||||
|
/* eventual ISO-9660 image size obtained from first 64k of input */
|
||||||
|
double iso_fs_size;
|
||||||
|
|
||||||
/* (sequential) fd chaining */
|
/* (sequential) fd chaining */
|
||||||
/* fds: 0=source, 1=dest */
|
/* fds: 0=source, 1=dest */
|
||||||
@ -159,6 +161,7 @@ int Cdrfifo_new(struct CdrfifO **ff, int source_fd, int dest_fd,
|
|||||||
o->get_counter= 0.0;
|
o->get_counter= 0.0;
|
||||||
o->empty_counter= 0.0;
|
o->empty_counter= 0.0;
|
||||||
o->full_counter= 0.0;
|
o->full_counter= 0.0;
|
||||||
|
o->iso_fs_size= -1.0;
|
||||||
for(i= 0; i<Cdrfifo_ffd_maX; i++) {
|
for(i= 0; i<Cdrfifo_ffd_maX; i++) {
|
||||||
o->follow_up_fds[i][0]= o->follow_up_fds[i][1]= -1;
|
o->follow_up_fds[i][0]= o->follow_up_fds[i][1]= -1;
|
||||||
o->follow_up_eop[i]= o->follow_up_sod[i]= -1;
|
o->follow_up_eop[i]= o->follow_up_sod[i]= -1;
|
||||||
@ -390,6 +393,13 @@ int Cdrfifo_get_min_fill(struct CdrfifO *o, int *total_min_fill,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int Cdrfifo_get_iso_fs_size(struct CdrfifO *o, double *size_in_bytes, int flag)
|
||||||
|
{
|
||||||
|
*size_in_bytes= o->iso_fs_size;
|
||||||
|
return(o->iso_fs_size>=2048);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/** Get counters which are mentioned by cdrecord at the end of burning.
|
/** Get counters which are mentioned by cdrecord at the end of burning.
|
||||||
It still has to be examined wether they mean what i believe they do.
|
It still has to be examined wether they mean what i believe they do.
|
||||||
*/
|
*/
|
||||||
@ -398,7 +408,7 @@ int Cdrfifo_get_cdr_counters(struct CdrfifO *o,
|
|||||||
double *empty_counter, double *full_counter,
|
double *empty_counter, double *full_counter,
|
||||||
int flag)
|
int flag)
|
||||||
{
|
{
|
||||||
*put_counter= o->put_counter;;
|
*put_counter= o->put_counter;
|
||||||
*get_counter= o->get_counter;
|
*get_counter= o->get_counter;
|
||||||
*empty_counter= o->empty_counter;
|
*empty_counter= o->empty_counter;
|
||||||
*full_counter= o->full_counter;
|
*full_counter= o->full_counter;
|
||||||
@ -870,6 +880,24 @@ int Cdrfifo_fill(struct CdrfifO *o, int size, int flag)
|
|||||||
if(ret==2)
|
if(ret==2)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#ifndef Cdrfifo_standalonE
|
||||||
|
{ int Scan_for_iso_size(unsigned char data[2048], double *size_in_bytes,
|
||||||
|
int flag);
|
||||||
|
int i;
|
||||||
|
double size;
|
||||||
|
|
||||||
|
/* try to obtain an ISO-9660 file system size */
|
||||||
|
for(i= 0; i<32*2048 && i+2048<=fill; i+=2048) {
|
||||||
|
ret= Scan_for_iso_size((unsigned char *) (o->buffer+i), &size, 0);
|
||||||
|
if(ret<=0)
|
||||||
|
continue;
|
||||||
|
o->iso_fs_size= size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
o->total_min_fill= fill;
|
o->total_min_fill= fill;
|
||||||
o->interval_min_fill= fill;
|
o->interval_min_fill= fill;
|
||||||
return(1);
|
return(1);
|
||||||
|
@ -117,6 +117,11 @@ int Cdrfifo_get_cdr_counters(struct CdrfifO *o,
|
|||||||
double *empty_counter, double *full_counter,
|
double *empty_counter, double *full_counter,
|
||||||
int flag);
|
int flag);
|
||||||
|
|
||||||
|
/** Inquire the eventually detected size of an eventual ISO-9660 file system
|
||||||
|
@return 0=no ISO resp. size detected, 1=size_in_bytes is valid
|
||||||
|
*/
|
||||||
|
int Cdrfifo_get_iso_fs_size(struct CdrfifO *o, double *size_in_bytes,int flag);
|
||||||
|
|
||||||
|
|
||||||
/** Check for pending data at the fifo's source file descriptor and wether the
|
/** Check for pending data at the fifo's source file descriptor and wether the
|
||||||
fifo is ready to take them. Simultaneously check the buffer for existing
|
fifo is ready to take them. Simultaneously check the buffer for existing
|
||||||
|
@ -2,7 +2,7 @@
|
|||||||
.\" First parameter, NAME, should be all caps
|
.\" First parameter, NAME, should be all caps
|
||||||
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
|
||||||
.\" other parameters are allowed: see man(7), man(1)
|
.\" other parameters are allowed: see man(7), man(1)
|
||||||
.TH CDRSKIN 1 "March 6, 2007"
|
.TH CDRSKIN 1 "July 19, 2007"
|
||||||
.\" Please adjust this date whenever revising the manpage.
|
.\" Please adjust this date whenever revising the manpage.
|
||||||
.\"
|
.\"
|
||||||
.\" Some roff macros, for reference:
|
.\" Some roff macros, for reference:
|
||||||
@ -190,12 +190,6 @@ DVD+R.
|
|||||||
Quite deliberately write mode -sao insists in the tradition of a predicted
|
Quite deliberately write mode -sao insists in the tradition of a predicted
|
||||||
track size and blank media, whereas -tao writes the tracks open ended and
|
track size and blank media, whereas -tao writes the tracks open ended and
|
||||||
allows appendable media.
|
allows appendable media.
|
||||||
.br
|
|
||||||
Currently DVD+R are always kept appendable regardless wether -multi is given
|
|
||||||
or not. This might change in future so it is strongly advised to already now
|
|
||||||
use
|
|
||||||
.B -multi
|
|
||||||
whenever the disc shall be kept appendable.
|
|
||||||
.PP
|
.PP
|
||||||
.B Overwriteable DVD Media:
|
.B Overwriteable DVD Media:
|
||||||
.br
|
.br
|
||||||
@ -231,7 +225,7 @@ it might be only the
|
|||||||
who is able to get this list without further
|
who is able to get this list without further
|
||||||
precautions.
|
precautions.
|
||||||
.br
|
.br
|
||||||
It is consensus that \fBchmod a+rw /dev/sg0\fP or \fBchmod a+rw /dev/hdc\fP
|
It is consensus that \fBchmod a+rw /dev/sr0\fP or \fBchmod a+rw /dev/hdc\fP
|
||||||
is less security sensitive than chmod u+s /usr/bin/cdrskin. The risk for the
|
is less security sensitive than chmod u+s /usr/bin/cdrskin. The risk for the
|
||||||
drive is somewhat higher but the overall system is much less at stake.
|
drive is somewhat higher but the overall system is much less at stake.
|
||||||
.br
|
.br
|
||||||
@ -249,7 +243,7 @@ See option -scanbus for getting a list of cdrecord style addresses.
|
|||||||
.br
|
.br
|
||||||
Further are accepted on Linux: links to libburn-suitable device files,
|
Further are accepted on Linux: links to libburn-suitable device files,
|
||||||
device files which have the same major and minor device number,
|
device files which have the same major and minor device number,
|
||||||
and device files which have the same SCSI address parameters (e.g. /dev/sr0).
|
and device files which have the same SCSI address parameters (e.g. /dev/sg0).
|
||||||
.br
|
.br
|
||||||
.SH OPTIONS
|
.SH OPTIONS
|
||||||
.TP
|
.TP
|
||||||
@ -275,9 +269,9 @@ Announces that the subsequent tracks are to be burned as audio.
|
|||||||
The source is supposed to be uncompressed headerless PCM, 44100 Hz, 16 bit,
|
The source is supposed to be uncompressed headerless PCM, 44100 Hz, 16 bit,
|
||||||
stereo. For little-endian byte order (which is usual on PCs) use option
|
stereo. For little-endian byte order (which is usual on PCs) use option
|
||||||
-swab. Unless marked explicitely by option -data, input files with suffix
|
-swab. Unless marked explicitely by option -data, input files with suffix
|
||||||
.wav are examined wether they have a header in MS-WAVE format confirming
|
".wav" are examined wether they have a header in MS-WAVE format confirming
|
||||||
those parameters and eventually raw audio data get extracted and burned as
|
those parameters and eventually raw audio data get extracted and burned as
|
||||||
audio track. Same is done for suffix .au and SUN Audio.
|
audio track. Same is done for suffix ".au" and SUN Audio.
|
||||||
.br
|
.br
|
||||||
Option -audio may be used only with CD media and not with DVD.
|
Option -audio may be used only with CD media and not with DVD.
|
||||||
.TP
|
.TP
|
||||||
@ -304,14 +298,14 @@ Format a DVD-RW to "Restricted Overwrite". The user should bring some patience.
|
|||||||
(Note: blank=format_overwrite* are not original cdrecord options.)
|
(Note: blank=format_overwrite* are not original cdrecord options.)
|
||||||
.TP
|
.TP
|
||||||
format_overwrite_quickest
|
format_overwrite_quickest
|
||||||
Like format_overwrite without creating a 128 MB trailblazer session.
|
Like format_overwrite without creating a 128 MiB trailblazer session.
|
||||||
Leads to "intermediate" state which only allows sequential write
|
Leads to "intermediate" state which only allows sequential write
|
||||||
beginning from address 0.
|
beginning from address 0.
|
||||||
The "intermediate" state ends after the first session of writing data.
|
The "intermediate" state ends after the first session of writing data.
|
||||||
.TP
|
.TP
|
||||||
format_overwrite_full
|
format_overwrite_full
|
||||||
For DVD-RW this is like format_overwrite but claims full media size
|
For DVD-RW this is like format_overwrite but claims full media size
|
||||||
rather than just 128 MB.
|
rather than just 128 MiB.
|
||||||
Most traditional formatting is attempted. No data get written.
|
Most traditional formatting is attempted. No data get written.
|
||||||
Much patience is required.
|
Much patience is required.
|
||||||
.br
|
.br
|
||||||
@ -371,8 +365,10 @@ even if attempted explicitely via "driveropts=burnfree".
|
|||||||
.TP
|
.TP
|
||||||
.BI \-dummy
|
.BI \-dummy
|
||||||
Try to perform the drive operations without actually affecting the inserted
|
Try to perform the drive operations without actually affecting the inserted
|
||||||
media. There is no guarantee that this will work with a particular combination
|
media. There is no warranty that this will work with a particular combination
|
||||||
of drive, media, and write mode. Blanking is prevented reliably, though.
|
of drive, media, and write mode. Blanking is prevented reliably, though.
|
||||||
|
To avoid inadverted real burning, -dummy refuses burn runs on anything but
|
||||||
|
CD-R[W] and DVD-R[W].
|
||||||
.TP
|
.TP
|
||||||
.BI \-eject
|
.BI \-eject
|
||||||
Eject the disc after work is done.
|
Eject the disc after work is done.
|
||||||
@ -386,6 +382,9 @@ write modes which libburn believes they are not supported by the drive.
|
|||||||
Another application is to enforce blanking or re-formatting of media
|
Another application is to enforce blanking or re-formatting of media
|
||||||
which appear to be in the desired blank or format state already.
|
which appear to be in the desired blank or format state already.
|
||||||
.br
|
.br
|
||||||
|
This option enables a burn run with option -dummy even if libburn believes
|
||||||
|
that drive and media will not simulate the write mode but will write for real.
|
||||||
|
.br
|
||||||
.B Caution:
|
.B Caution:
|
||||||
Use this only when in urgent need.
|
Use this only when in urgent need.
|
||||||
.TP
|
.TP
|
||||||
@ -408,6 +407,29 @@ option fifo_start_at=size.
|
|||||||
.BI gracetime= seconds
|
.BI gracetime= seconds
|
||||||
Set the grace time before starting to write. (Default is 0)
|
Set the grace time before starting to write. (Default is 0)
|
||||||
.TP
|
.TP
|
||||||
|
.BI -isosize
|
||||||
|
The next track following this option will try to obtain its source size from
|
||||||
|
the header information out of the first few blocks of the source data.
|
||||||
|
If these blocks indicate an ISO-9660 filesystem then its declared size
|
||||||
|
will be used under the assumption that it is a single session filesystem.
|
||||||
|
.br
|
||||||
|
If not, then the burn run will be aborted.
|
||||||
|
.br
|
||||||
|
The range of -isosize is exactly one track. Further tracks may be preceeded
|
||||||
|
by further -isosize options, though. At least 15 blocks of padding will be
|
||||||
|
added to each -isosize track. But be advised to rather use padsize=300k.
|
||||||
|
.br
|
||||||
|
This option can be performed on track sources which are regular files or block
|
||||||
|
devices. For the first track of the session it can be performed on any type
|
||||||
|
of source if there is a fifo of at least 64 kiB. See option fs= .
|
||||||
|
.TP
|
||||||
|
.BI minbuf= percentage
|
||||||
|
Equivalent to:
|
||||||
|
.br
|
||||||
|
modesty_on_drive=1:min_percent=<percentage>:max_percent=95
|
||||||
|
.br
|
||||||
|
Percentage is permissible between 25 and 95.
|
||||||
|
.TP
|
||||||
.BI msifile= path
|
.BI msifile= path
|
||||||
Run option -msinfo and copy the result line into the file given by path.
|
Run option -msinfo and copy the result line into the file given by path.
|
||||||
Unlike -msinfo this option does not redirect all normal output away from
|
Unlike -msinfo this option does not redirect all normal output away from
|
||||||
@ -451,7 +473,7 @@ to be no use for audio tracks with incomplete last sector, this option applies
|
|||||||
only to data tracks. There it is default.
|
only to data tracks. There it is default.
|
||||||
.TP
|
.TP
|
||||||
.BI \-pad
|
.BI \-pad
|
||||||
Add 30 kB of trailing zeros to each data track. (This is not sufficient to
|
Add 30 kiB of trailing zeros to each data track. (This is not sufficient to
|
||||||
avoid problems with various CD-ROM read drivers.)
|
avoid problems with various CD-ROM read drivers.)
|
||||||
.TP
|
.TP
|
||||||
.BI padsize= size
|
.BI padsize= size
|
||||||
@ -503,6 +525,9 @@ Set speed of drive. With data CD, 1x speed corresponds to a throughput of
|
|||||||
150,000 bytes/second. With DVD, 1x = 1,385,000 bytes/second.
|
150,000 bytes/second. With DVD, 1x = 1,385,000 bytes/second.
|
||||||
It is not an error to set a speed higher than is suitable for drive
|
It is not an error to set a speed higher than is suitable for drive
|
||||||
and media. One should stay within a realistic speed range, though.
|
and media. One should stay within a realistic speed range, though.
|
||||||
|
Special speed settings are:
|
||||||
|
.br
|
||||||
|
0 = minimal speed , -1 = maximal speed (default).
|
||||||
.TP
|
.TP
|
||||||
.BI \-swab
|
.BI \-swab
|
||||||
Announce that the raw audio data source of subsequent tracks is byte swapped
|
Announce that the raw audio data source of subsequent tracks is byte swapped
|
||||||
@ -570,6 +595,12 @@ somebody who had a look into the program sourcecode.
|
|||||||
Alphabetical list of options which are genuine to cdrskin and intended for
|
Alphabetical list of options which are genuine to cdrskin and intended for
|
||||||
normal use:
|
normal use:
|
||||||
.TP
|
.TP
|
||||||
|
.BI \--adjust_speed_to_drive
|
||||||
|
Curb explicitely given speed= values to the maximum which is announced by the
|
||||||
|
drive for the loaded media. By default, such an adjustment is only made with
|
||||||
|
pseudo-speeds 0 and -1 whereas speed settings > 0 are sent unchanged to the
|
||||||
|
drive which will then choose an appropriate speed on its own.
|
||||||
|
.TP
|
||||||
.BI \--allow_setuid
|
.BI \--allow_setuid
|
||||||
Disable the loud warning about insecure discrepance between login user and
|
Disable the loud warning about insecure discrepance between login user and
|
||||||
effective user which indicates application of chmod u+s to the program binary.
|
effective user which indicates application of chmod u+s to the program binary.
|
||||||
@ -678,8 +709,8 @@ string and eventual output of -msinfo.
|
|||||||
.TP
|
.TP
|
||||||
.BI write_start_address= byte_offset
|
.BI write_start_address= byte_offset
|
||||||
Set the address on media where to start writing the track. With DVD+RW or
|
Set the address on media where to start writing the track. With DVD+RW or
|
||||||
DVD-RAM byte_offset must be aligned to 2 KB blocks, but better is 32 kB.
|
DVD-RAM byte_offset must be aligned to 2 kiB blocks, but better is 32 kiB.
|
||||||
With DVD-RW 32 kB alignment is mandatory.
|
With DVD-RW 32 kiB alignment is mandatory.
|
||||||
.br
|
.br
|
||||||
Other media are not suitable for this option yet.
|
Other media are not suitable for this option yet.
|
||||||
.PP
|
.PP
|
||||||
@ -712,7 +743,7 @@ translate cdrecord addresses into cdrskin addresses.
|
|||||||
dev=. <to> is the address to be used instead whenever <from> is given.
|
dev=. <to> is the address to be used instead whenever <from> is given.
|
||||||
More than one translation instruction can be given in one cdrskin run.
|
More than one translation instruction can be given in one cdrskin run.
|
||||||
.br
|
.br
|
||||||
E.g.: dev_translation=+ATA:1,0,0+/dev/sg1 dev_translation=+ATA:1,1,0+/dev/sg2
|
E.g.: dev_translation=+ATA:1,0,0+/dev/sr1 dev_translation=+ATA:1,1,0+/dev/sr2
|
||||||
.TP
|
.TP
|
||||||
.BI \--drive_abort_on_busy
|
.BI \--drive_abort_on_busy
|
||||||
Linux specific: Abort process if a busy drive is encountered.
|
Linux specific: Abort process if a busy drive is encountered.
|
||||||
@ -721,14 +752,33 @@ Linux specific: Abort process if a busy drive is encountered.
|
|||||||
Linux specific: Try to wait for a busy drive to become free.
|
Linux specific: Try to wait for a busy drive to become free.
|
||||||
This is not guaranteed to work with all drivers. Some need nonblocking i/o.
|
This is not guaranteed to work with all drivers. Some need nonblocking i/o.
|
||||||
.TP
|
.TP
|
||||||
|
.BI \--drive_f_setlk
|
||||||
|
Linux specific: Try to get exclusive lock on drive device file via fcntl(2).
|
||||||
|
.TP
|
||||||
.BI \--drive_not_exclusive
|
.BI \--drive_not_exclusive
|
||||||
|
Linux specific: Combine --drive_not_f_setlk and --drive_not_o_excl.
|
||||||
|
.TP
|
||||||
|
.BI \--drive_not_f_setlk
|
||||||
|
Linux specific: Do not try to get exclusive lock on drive device file via
|
||||||
|
fcntl(2).
|
||||||
|
.TP
|
||||||
|
.BI \--drive_not_o_excl
|
||||||
Linux specific: Do not ask the operating system to prevent opening busy drives.
|
Linux specific: Do not ask the operating system to prevent opening busy drives.
|
||||||
Wether this leads to senseful behavior depends on operating system and kernel.
|
Wether this leads to senseful behavior depends on operating system and kernel.
|
||||||
.TP
|
.TP
|
||||||
|
.BI drive_scsi_dev_family= sr | scd | sg
|
||||||
|
Linux specific: Select a SCSI device file family to be used for drive command
|
||||||
|
transactions. Normally this is /dev/sgN on kernel versions < 2.6 and /dev/srN
|
||||||
|
on kernels >= 2.6 . This option allows to explicitely override that default
|
||||||
|
in order to meet other programs at a common device file for each drive.
|
||||||
|
On kernel 2.4 families sr and scd will find no drives.
|
||||||
|
.br
|
||||||
|
Device file family /dev/hdX on kernel >= 2.6 is not affected by this setting.
|
||||||
|
.TP
|
||||||
.BI \--drive_scsi_exclusive
|
.BI \--drive_scsi_exclusive
|
||||||
Linux specific:
|
Linux specific:
|
||||||
Try to exclusively reserve device files /dev/srN, /dev/scdM, /dev/stK of drive.
|
Try to exclusively reserve device files /dev/srN, /dev/scdM, /dev/sgK of drives.
|
||||||
this would be helpful to protect against collisions with program growisofs.
|
This would be helpful to protect against collisions with program growisofs.
|
||||||
Regrettably on Linux kernel 2.4 with ide-scsi emulation this seems not to
|
Regrettably on Linux kernel 2.4 with ide-scsi emulation this seems not to
|
||||||
work. Wether it becomes helpful with new Linux systems has to be evaluated.
|
work. Wether it becomes helpful with new Linux systems has to be evaluated.
|
||||||
.TP
|
.TP
|
||||||
@ -762,6 +812,30 @@ Try to ignore any signals rather than to abort the program. This is not a
|
|||||||
very good idea. You might end up waiting a very long time for cdrskin
|
very good idea. You might end up waiting a very long time for cdrskin
|
||||||
to finish.
|
to finish.
|
||||||
.TP
|
.TP
|
||||||
|
.BI modesty_on_drive= <mode>[:min_percent=<num>][:max_percent=<num>]
|
||||||
|
Mode 1 keeps the program from trying to write to the burner drive while its
|
||||||
|
buffer is in danger to be filled by more than max_percent. If this filling is
|
||||||
|
exceeded then the program will wait until the filling is at most min_percent.
|
||||||
|
.br
|
||||||
|
This can ease the load on operating system and drive controller and thus help
|
||||||
|
with achieving better input bandwidth if disk and burner are not on independent
|
||||||
|
controllers (like hda and hdb). Unsufficient input bandwidth is indicated by
|
||||||
|
output "(fifo xy%)" of option -v if xy is lower than 90 for some time.
|
||||||
|
modesty_on_drive= might hamper output bandwidth and cause buffer underruns.
|
||||||
|
.br
|
||||||
|
To have max_percent larger than the burner's best actual
|
||||||
|
buffer fill has the same effect as min_percent==max_percent. Some burners
|
||||||
|
do not use their full buffer with all media types. Watch output "[buf xy%]"
|
||||||
|
of option -v to get an impression of the actual buffer usage. Some burners
|
||||||
|
are not suitable because they report buffer fill with granularity too large
|
||||||
|
in size or time.
|
||||||
|
.br
|
||||||
|
Mode 0 disables this feature. Mode -1 keeps it unchanged. Default is:
|
||||||
|
.br
|
||||||
|
modesty_on_drive=0:min_percent=65:max_percent=95
|
||||||
|
.br
|
||||||
|
Percentages are permissible in the range of 25 to 100.
|
||||||
|
.TP
|
||||||
.BI \--no_abort_handler
|
.BI \--no_abort_handler
|
||||||
On signals exit even if the drive is in busy state. This is not a very good
|
On signals exit even if the drive is in busy state. This is not a very good
|
||||||
idea. You might end up with a stuck drive that refuses to hand out the media.
|
idea. You might end up with a stuck drive that refuses to hand out the media.
|
||||||
@ -778,7 +852,7 @@ Partly Linux specific:
|
|||||||
Such opening is needed for Bus,Target,Lun addresses unless option
|
Such opening is needed for Bus,Target,Lun addresses unless option
|
||||||
--old_pseudo_scsi_adr is given. It is also needed to resolve device file
|
--old_pseudo_scsi_adr is given. It is also needed to resolve device file
|
||||||
addresses which are not listed with cdrskin --devices but nevertheless point
|
addresses which are not listed with cdrskin --devices but nevertheless point
|
||||||
to a usable drive. (Like /dev/sr0 using the same SCSI address as /dev/sg0.)
|
to a usable drive. (Like /dev/sg0 using the same SCSI address as /dev/sr0.)
|
||||||
.TP
|
.TP
|
||||||
.BI \--old_pseudo_scsi_adr
|
.BI \--old_pseudo_scsi_adr
|
||||||
Linux specific:
|
Linux specific:
|
||||||
@ -899,7 +973,7 @@ fs=16m
|
|||||||
.br
|
.br
|
||||||
.SH SEE ALSO
|
.SH SEE ALSO
|
||||||
.TP
|
.TP
|
||||||
Formatting track sources for cdrskin:
|
Formatting data track sources for cdrskin:
|
||||||
.br
|
.br
|
||||||
.BR mkisofs (8),
|
.BR mkisofs (8),
|
||||||
.BR genisoimage (8),
|
.BR genisoimage (8),
|
||||||
|
File diff suppressed because it is too large
Load Diff
@ -12,7 +12,7 @@
|
|||||||
|
|
||||||
<CENTER>
|
<CENTER>
|
||||||
<A HREF="http://en.wikipedia.org/wiki/D%C3%B6ner_kebab">
|
<A HREF="http://en.wikipedia.org/wiki/D%C3%B6ner_kebab">
|
||||||
<IMG SRC="doener_150x200_tr_octx.gif" BORDER=0
|
<IMG SRC="doener_150x200_tr_octx.png" BORDER=0
|
||||||
ALT="cdrskin logo: Doener mit Scharf">
|
ALT="cdrskin logo: Doener mit Scharf">
|
||||||
</A>
|
</A>
|
||||||
<P><H2> Homepage of </H2>
|
<P><H2> Homepage of </H2>
|
||||||
@ -56,9 +56,9 @@ and to MMC-5 for DVD).
|
|||||||
GPL software included:<BR>
|
GPL software included:<BR>
|
||||||
</H2>
|
</H2>
|
||||||
<DL>
|
<DL>
|
||||||
<DT>libburn-0.3.4</DT>
|
<DT>libburn-0.3.8</DT>
|
||||||
<DD>(by Derek Foreman, Ben Jansens, and team of libburnia.pykix.org)</DD>
|
<DD>(by Derek Foreman, Ben Jansens, and team of libburnia.pykix.org)</DD>
|
||||||
<DD>transfers data to CD</DD>
|
<DD>transfers data to CD and DVD</DD>
|
||||||
</DL>
|
</DL>
|
||||||
</P>
|
</P>
|
||||||
|
|
||||||
@ -81,24 +81,19 @@ Ports to other usable systems are appreciated. Reports are welcome.
|
|||||||
<P>
|
<P>
|
||||||
<H2>Commands:</H2>
|
<H2>Commands:</H2>
|
||||||
<DL>
|
<DL>
|
||||||
<DT>The goal is to provide some of cdrecord's options in a compatible way.
|
<DT>The most common options of cdrecord for data and audio on CD media
|
||||||
This has been achieved quite sufficiently for the needs of backup tool
|
are provided in a compatible way.<BR>
|
||||||
<A HREF="http://scdbackup.sourceforge.net/main_eng.html">scdbackup</A>
|
On single layer DVD media cdrskin is able to perform any recording job
|
||||||
and for data CD projects of <A HREF="http://www.k3b.org">K3b</A>
|
which is possible with cdrecord.
|
||||||
(see <A HREF="#examples">examples</A>).
|
Other than with cdrecord, options -multi and -tao are supported with
|
||||||
Suitability for audio CD frontends has been improved much and is now being
|
certain DVD types.
|
||||||
evaluated.<BR>
|
</DT>
|
||||||
Most DVD types are written in pseudo -tao modes which are very different
|
|
||||||
from the write mode DAO used by cdrecord(-ProDVD). With DVD-R[W] cdrskin
|
|
||||||
can use this write mode, too.<BR>
|
|
||||||
Further enhancements depend on people who can describe and discuss their
|
|
||||||
wishes as well as on the development of libburn.</DT>
|
|
||||||
<BR><BR>
|
<BR><BR>
|
||||||
<DT>Get an overview of drives and their addresses</DT>
|
<DT>Get an overview of drives and their addresses</DT>
|
||||||
<DD>#<KBD> cdrskin -scanbus</KBD></DD>
|
<DD>#<KBD> cdrskin -scanbus</KBD></DD>
|
||||||
<DD>#<KBD> cdrskin dev=ATA -scanbus</KBD></DD>
|
<DD>#<KBD> cdrskin dev=ATA -scanbus</KBD></DD>
|
||||||
<DD>#<KBD> cdrskin --devices</KBD></DD>
|
<DD>#<KBD> cdrskin --devices</KBD></DD>
|
||||||
<DT>Being superuser avoids permission problems with /dev/sgN resp. /dev/hdX .
|
<DT>Being superuser avoids permission problems with /dev/srN resp. /dev/hdX .
|
||||||
</DT>
|
</DT>
|
||||||
<DT>Ordinary users should then get granted rw access to the /dev files
|
<DT>Ordinary users should then get granted rw access to the /dev files
|
||||||
as listed by option --devices.</DT>
|
as listed by option --devices.</DT>
|
||||||
@ -160,7 +155,6 @@ as listed by option --devices.</DT>
|
|||||||
<DT>Read the detailed manual page:</DT>
|
<DT>Read the detailed manual page:</DT>
|
||||||
<DD>$<KBD> <A HREF="man_1_cdrskin.html">man cdrskin</A></KBD></DD>
|
<DD>$<KBD> <A HREF="man_1_cdrskin.html">man cdrskin</A></KBD></DD>
|
||||||
</DL>
|
</DL>
|
||||||
|
|
||||||
<DL>
|
<DL>
|
||||||
<DT>Read about the standard for which cdrskin is striving:</DT>
|
<DT>Read about the standard for which cdrskin is striving:</DT>
|
||||||
<DD>$<KBD>
|
<DD>$<KBD>
|
||||||
@ -171,6 +165,9 @@ man cdrecord</A></KBD></DD>
|
|||||||
this "don't bother Joerg" demand.)
|
this "don't bother Joerg" demand.)
|
||||||
</DD>
|
</DD>
|
||||||
</DL>
|
</DL>
|
||||||
|
|
||||||
|
Testers wanted who are willing to risk some double layer DVD media.
|
||||||
|
|
||||||
</P>
|
</P>
|
||||||
|
|
||||||
<HR>
|
<HR>
|
||||||
@ -178,8 +175,8 @@ man cdrecord</A></KBD></DD>
|
|||||||
<P>
|
<P>
|
||||||
<DL>
|
<DL>
|
||||||
<DT>Download as source code (see README):</DT>
|
<DT>Download as source code (see README):</DT>
|
||||||
<DD><A HREF="cdrskin-0.3.4.pl00.tar.gz">cdrskin-0.3.4.pl00.tar.gz</A>
|
<DD><A HREF="cdrskin-0.3.8.pl00.tar.gz">cdrskin-0.3.8.pl00.tar.gz</A>
|
||||||
(570 KB).
|
(615 KB).
|
||||||
</DD>
|
</DD>
|
||||||
<DD>
|
<DD>
|
||||||
The "stable" cdrskin tarballs are source code identical with "stable"
|
The "stable" cdrskin tarballs are source code identical with "stable"
|
||||||
@ -189,14 +186,14 @@ cdrskin is part of libburn - full libburn is provided with cdrskin releases.
|
|||||||
</DD>
|
</DD>
|
||||||
<DD> </DD>
|
<DD> </DD>
|
||||||
<DT>Download as single x86 binaries (untar and move to /usr/bin/cdrskin):</DT>
|
<DT>Download as single x86 binaries (untar and move to /usr/bin/cdrskin):</DT>
|
||||||
<DD><A HREF="cdrskin_0.3.4.pl00-x86-suse9_0.tar.gz">
|
<DD><A HREF="cdrskin_0.3.8.pl00-x86-suse9_0.tar.gz">
|
||||||
cdrskin_0.3.4.pl00-x86-suse9_0.tar.gz</A>, (80 KB),
|
cdrskin_0.3.8.pl00-x86-suse9_0.tar.gz</A>, (90 KB),
|
||||||
<DL>
|
<DL>
|
||||||
<DD>runs on SuSE 9.0 (2.4.21) , RIP-14.4 (2.6.14) ,
|
<DD>runs on SuSE 9.0 (2.4.21) , RIP-14.4 (2.6.14) ,
|
||||||
Gentoo (2.6.15 x86_64 Athlon).</DD>
|
Gentoo (2.6.15 x86_64 Athlon).</DD>
|
||||||
</DL>
|
</DL>
|
||||||
<DD><A HREF="cdrskin_0.3.4.pl00-x86-suse9_0-static.tar.gz">
|
<DD><A HREF="cdrskin_0.3.8.pl00-x86-suse9_0-static.tar.gz">
|
||||||
cdrskin_0.3.4.pl00-x86-suse9_0-static.tar.gz</A>, (285 KB), -static compiled,
|
cdrskin_0.3.8.pl00-x86-suse9_0-static.tar.gz</A>, (290 KB), -static compiled,
|
||||||
<DL>
|
<DL>
|
||||||
<DD>runs on SuSE 7.2 (2.4.4), and on the systems above.</DD>
|
<DD>runs on SuSE 7.2 (2.4.4), and on the systems above.</DD>
|
||||||
</DL>
|
</DL>
|
||||||
@ -223,16 +220,18 @@ cdrskin_0.3.4.pl00-x86-suse9_0-static.tar.gz</A>, (285 KB), -static compiled,
|
|||||||
<HR>
|
<HR>
|
||||||
|
|
||||||
<P>
|
<P>
|
||||||
Enhancements towards previous stable version cdrskin-0.3.2:
|
Enhancements towards previous stable version cdrskin-0.3.4:
|
||||||
<UL>
|
<UL>
|
||||||
<LI>Multi-session burning to DVD+R</LI>
|
<LI>Now able to cope with the peculiarities of Linux 2.4 USB</LI>
|
||||||
<LI>New option --tell_media_space tells the maximum size for the next burn</LI>
|
<LI>Refusal to perform -dummy runs on media which cannot simulate burning</LI>
|
||||||
<LI>New option assert_write_lba= prevents inadverted writing to appendable
|
<LI>Precautions against using the burner drive as track source</LI>
|
||||||
<LI>Bug fix: Multi-track runs with fifo could stall in rare cases</LI>
|
<LI>New option modesty_on_drive= may help with hda -> hdb burns</LI>
|
||||||
|
<LI>New option minbuf= , cdrecord compatible frontend of modesty_on_drive=</LI>
|
||||||
|
<LI>New option --adjust_speed_to_drive</LI>
|
||||||
</UL>
|
</UL>
|
||||||
|
|
||||||
<!--
|
<!--
|
||||||
Bug fixes towards cdrskin-0.3.4.pl00:
|
Bug fixes towards cdrskin-0.3.8.pl00:
|
||||||
<UL>
|
<UL>
|
||||||
<LI>none yet</LI>
|
<LI>none yet</LI>
|
||||||
</UL>
|
</UL>
|
||||||
@ -244,17 +243,17 @@ Enhancements towards previous stable version cdrskin-0.3.2:
|
|||||||
|
|
||||||
<P>
|
<P>
|
||||||
<DL>
|
<DL>
|
||||||
<DT><H3>Development snapshot, version 0.3.5 :</H3></DT>
|
<DT><H3>Development snapshot, version 0.3.9 :</H3></DT>
|
||||||
<DD>Enhancements towards stable version 0.3.4.pl00:
|
<DD>Enhancements towards stable version 0.3.8.pl00:
|
||||||
<UL>
|
<UL>
|
||||||
<LI>none yet</LI>
|
<LI>none yet</LI>
|
||||||
</UL>
|
</UL>
|
||||||
</DD>
|
</DD>
|
||||||
<DD> </DD>
|
<DD> </DD>
|
||||||
<DD><A HREF="README_cdrskin_devel">README 0.3.5</A>
|
<DD><A HREF="README_cdrskin_devel">README 0.3.9</A>
|
||||||
<DD><A HREF="cdrskin__help_devel">cdrskin_0.3.5 --help</A></DD>
|
<DD><A HREF="cdrskin__help_devel">cdrskin_0.3.9 --help</A></DD>
|
||||||
<DD><A HREF="cdrskin_help_devel">cdrskin_0.3.5 -help</A></DD>
|
<DD><A HREF="cdrskin_help_devel">cdrskin_0.3.9 -help</A></DD>
|
||||||
<DD><A HREF="man_1_cdrskin_devel.html">man cdrskin (as of 0.3.5)</A></DD>
|
<DD><A HREF="man_1_cdrskin_devel.html">man cdrskin (as of 0.3.9)</A></DD>
|
||||||
<DD> </DD>
|
<DD> </DD>
|
||||||
<DT>Maintainers of cdrskin unstable packages please use SVN of
|
<DT>Maintainers of cdrskin unstable packages please use SVN of
|
||||||
<A HREF="http://libburnia.pykix.org"> libburnia.pykix.org</A></DT>
|
<A HREF="http://libburnia.pykix.org"> libburnia.pykix.org</A></DT>
|
||||||
@ -274,15 +273,15 @@ admins with full system souvereignty.</DT>
|
|||||||
<A HREF="README_cdrskin_devel">upcoming README</A> ):
|
<A HREF="README_cdrskin_devel">upcoming README</A> ):
|
||||||
</DD>
|
</DD>
|
||||||
<DD>
|
<DD>
|
||||||
<A HREF="cdrskin-0.3.5.tar.gz">cdrskin-0.3.5.tar.gz</A>
|
<A HREF="cdrskin-0.3.9.tar.gz">cdrskin-0.3.9.tar.gz</A>
|
||||||
(570 KB).
|
(615 KB).
|
||||||
</DD>
|
</DD>
|
||||||
<DD>Binary (untar and move to /usr/bin/cdrskin):</DD>
|
<DD>Binary (untar and move to /usr/bin/cdrskin):</DD>
|
||||||
<DD><A HREF="cdrskin_0.3.5-x86-suse9_0.tar.gz">
|
<DD><A HREF="cdrskin_0.3.9-x86-suse9_0.tar.gz">
|
||||||
cdrskin_0.3.5-x86-suse9_0.tar.gz</A>, (80 KB).
|
cdrskin_0.3.9-x86-suse9_0.tar.gz</A>, (90 KB).
|
||||||
</DD>
|
</DD>
|
||||||
<DD><A HREF="cdrskin_0.3.5-x86-suse9_0-static.tar.gz">
|
<DD><A HREF="cdrskin_0.3.9-x86-suse9_0-static.tar.gz">
|
||||||
cdrskin_0.3.5-x86-suse9_0-static.tar.gz</A>, (280 KB)
|
cdrskin_0.3.9-x86-suse9_0-static.tar.gz</A>, (290 KB)
|
||||||
</DD>
|
</DD>
|
||||||
</DL>
|
</DL>
|
||||||
</P>
|
</P>
|
||||||
@ -310,13 +309,13 @@ provide libburn with invaluable examples on how to deal with DVD media.
|
|||||||
<P>
|
<P>
|
||||||
<DL>
|
<DL>
|
||||||
<DT>Example for a setup of device permissions. To be done by the superuser:</DT>
|
<DT>Example for a setup of device permissions. To be done by the superuser:</DT>
|
||||||
<DT>(CD devices which offer no r-permission are invisible to normal users.)</DT>
|
<DT>(CD devices which offer no rw-permission are invisible to normal users.)
|
||||||
<DT>(CD devices which offer no w-permission are not useable.)</DT>
|
</DT>
|
||||||
<DD># <KBD><B>cdrskin --devices</B></KBD></DD>
|
<DD># <KBD><B>cdrskin --devices</B></KBD></DD>
|
||||||
<DD><KBD>...</KBD></DD>
|
<DD><KBD>...</KBD></DD>
|
||||||
<DD><KBD>0 dev='/dev/sg0' rwrwr- : 'TEAC' 'CD-ROM CD-532S'</KBD></DD>
|
<DD><KBD>0 dev='/dev/sr0' rwrwr- : 'TEAC' 'CD-ROM CD-532S'</KBD></DD>
|
||||||
<DD><KBD>1 dev='/dev/hdc' rwrw-- : 'LITE-ON' 'LTR-48125S'</KBD></DD>
|
<DD><KBD>1 dev='/dev/hdc' rwrw-- : 'LITE-ON' 'LTR-48125S'</KBD></DD>
|
||||||
<DD># <KBD><B>chmod a+rw /dev/sg0 /dev/hdc</B></KBD></DD>
|
<DD># <KBD><B>chmod a+rw /dev/sr0 /dev/hdc</B></KBD></DD>
|
||||||
</DL>
|
</DL>
|
||||||
</P>
|
</P>
|
||||||
|
|
||||||
@ -353,7 +352,7 @@ is a GUI frontend which uses cdrecord for CD burning.)
|
|||||||
<DD>$ <KBD><B>export SCDBACKUP_USE_CDRSKIN=1</B></KBD></DD>
|
<DD>$ <KBD><B>export SCDBACKUP_USE_CDRSKIN=1</B></KBD></DD>
|
||||||
<DD>$ <KBD><B>./CONFIGURE_CD</B></KBD></DD>
|
<DD>$ <KBD><B>./CONFIGURE_CD</B></KBD></DD>
|
||||||
<DD><KBD>...</KBD></DD>
|
<DD><KBD>...</KBD></DD>
|
||||||
<DD><KBD>cdrskin 0.3.4 : limited cdrecord compatibility wrapper for libburn</KBD></DD>
|
<DD><KBD>cdrskin 0.3.8 : limited cdrecord compatibility wrapper for libburn</KBD></DD>
|
||||||
</DL>
|
</DL>
|
||||||
If your system is stricken with some ill CD device then this can stall
|
If your system is stricken with some ill CD device then this can stall
|
||||||
and you will have to press <KBD>Ctrl+C</KBD> to abort.
|
and you will have to press <KBD>Ctrl+C</KBD> to abort.
|
||||||
@ -430,7 +429,7 @@ I owe him much. For cdrecord, for mkisofs, for star. Chapeau.
|
|||||||
<BR><BR>
|
<BR><BR>
|
||||||
-->
|
-->
|
||||||
<A HREF="http://en.wikipedia.org/wiki/D%C3%B6ner_kebab">
|
<A HREF="http://en.wikipedia.org/wiki/D%C3%B6ner_kebab">
|
||||||
<IMG SRC="doener_150x200_tr.gif" BORDER=0
|
<IMG SRC="doener_150x200_tr.png" BORDER=0
|
||||||
ALT="cdrskin logo: Doener mit Scharf"></A>
|
ALT="cdrskin logo: Doener mit Scharf"></A>
|
||||||
<BR><BR>
|
<BR><BR>
|
||||||
<FONT SIZE=+0>Enjoying free Open Source hosting by <A HREF="http://www.webframe.org">www.webframe.org</A><BR>
|
<FONT SIZE=+0>Enjoying free Open Source hosting by <A HREF="http://www.webframe.org">www.webframe.org</A><BR>
|
||||||
|
@ -1 +1 @@
|
|||||||
#define Cdrskin_timestamP "2007.03.12.110001"
|
#define Cdrskin_timestamP "2007.07.20.120001"
|
||||||
|
@ -34,6 +34,10 @@ Deliberate deviations of cdrskin from cdrecord compatibility:
|
|||||||
Option blank=fast is the same as blank=all in order to achieve media which
|
Option blank=fast is the same as blank=all in order to achieve media which
|
||||||
are capable of Incremental Streaming.
|
are capable of Incremental Streaming.
|
||||||
|
|
||||||
|
+ It has not been evaluated how far -isosize is compatible with the original
|
||||||
|
cdrecord option. man cdrecord forbids stdin as source, cdrskin allows it
|
||||||
|
if a fifo is used.
|
||||||
|
|
||||||
|
|
||||||
------------------------------------------------------------------------------
|
------------------------------------------------------------------------------
|
||||||
Changelog
|
Changelog
|
||||||
@ -3327,10 +3331,14 @@ Made number transition to 0.3.4 and activated development documentation
|
|||||||
+ cdrskin/add_ts_changes_to_libburn_0_3_5
|
+ cdrskin/add_ts_changes_to_libburn_0_3_5
|
||||||
Updated cdrskin tarball generator
|
Updated cdrskin tarball generator
|
||||||
|
|
||||||
12 Mar 2007 [tag ]
|
12 Mar 2007 [tag 763]
|
||||||
cdrskin/changelog.txt
|
cdrskin/changelog.txt
|
||||||
Documented most recent changes
|
Documented most recent changes
|
||||||
|
|
||||||
|
12 Mar 2007 [tag 764]
|
||||||
|
README
|
||||||
|
Removed redundant sentence
|
||||||
|
|
||||||
----------------------------- release - cdrskin-0.3.4.pl00 - 2007.03.12.110001
|
----------------------------- release - cdrskin-0.3.4.pl00 - 2007.03.12.110001
|
||||||
* Multi-session burning to DVD+R
|
* Multi-session burning to DVD+R
|
||||||
* New option --tell_media_space tells the maximum size for the next burn
|
* New option --tell_media_space tells the maximum size for the next burn
|
||||||
@ -3338,24 +3346,579 @@ Documented most recent changes
|
|||||||
* Bug fix: Multi-track runs with fifo could stall in rare cases
|
* Bug fix: Multi-track runs with fifo could stall in rare cases
|
||||||
|
|
||||||
|
|
||||||
|
2007.03.12.155600 [765]
|
||||||
|
Makefile.am
|
||||||
|
configure.ac
|
||||||
|
README
|
||||||
|
cdrskin/cdrskin.c
|
||||||
|
cdrskin/README
|
||||||
|
cdrskin/compile_cdrskin.sh
|
||||||
|
cdrskin/cdrskin_timestamp.h
|
||||||
|
cdrskin/cdrskin_eng.html
|
||||||
|
Made number transition to 0.3.5
|
||||||
|
|
||||||
|
12 Mar 2007 [766]
|
||||||
|
- cdrskin/add_ts_changes_to_libburn_0_3_2
|
||||||
|
- cdrskin/add_ts_changes_to_libburn_0_3_3
|
||||||
|
+ cdrskin/add_ts_changes_to_libburn_0_3_4
|
||||||
|
+ cdrskin/add_ts_changes_to_libburn_0_3_5
|
||||||
|
Updated cdrskin tarball generator
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------ cycle - cdrskin-0.3.5 - 2007.03.12.160658
|
||||||
|
|
||||||
|
14 Mar 2007 [767]
|
||||||
|
cdrskin/cdrskin_eng.html
|
||||||
|
Corrected truncated sentence and file sizes
|
||||||
|
|
||||||
|
14 Mar 2007 [768]
|
||||||
|
cdrskin/changelog.txt
|
||||||
|
Next cdrskin-0.3.5 cycle
|
||||||
|
|
||||||
|
2007.03.14.133618 [769]
|
||||||
|
libburn/libburn.h
|
||||||
|
libburn/init.c
|
||||||
|
libburn/sg-linux.c
|
||||||
|
cdrskin/cdrskin.c
|
||||||
|
cdrskin/cdrskin.1
|
||||||
|
New option drive_scsi_dev_family=sr|scd|sg
|
||||||
|
|
||||||
|
2007.03.15.194531 [770]
|
||||||
|
libburn/drive.c
|
||||||
|
React properly on drive stating that it cannot write any media
|
||||||
|
|
||||||
|
2007.03.15.195005 [771]
|
||||||
|
libburn/spc.h
|
||||||
|
libburn/spc.c
|
||||||
|
libburn/sbc.c
|
||||||
|
After loading tray wait for unit to become ready or to report some clear error
|
||||||
|
|
||||||
|
2007.03.15.195251 [772]
|
||||||
|
cdrskin/cdrskin.c
|
||||||
|
Moved manual device family decision to a sufficiently early stage
|
||||||
|
|
||||||
|
2007.03.15.195428 [773]
|
||||||
|
libburn/mmc.c
|
||||||
|
Kept mmc_get_configuration() from believing the announcement of 1 GB reply
|
||||||
|
|
||||||
|
2007.03.15.195534 [774]
|
||||||
|
libburn/sg-linux.c
|
||||||
|
Trying to recognize kernel >= 2.6 and use /dev/sr by default
|
||||||
|
|
||||||
|
15 Mar 2007 [775]
|
||||||
|
cdrskin/cdrskin.1
|
||||||
|
Updated drive_scsi_dev_family=
|
||||||
|
|
||||||
|
15 Mar 2007 [776]
|
||||||
|
cdrskin/changelog.txt
|
||||||
|
Next cdrskin-0.3.5 cycle
|
||||||
|
|
||||||
|
------------------------------------ cycle - cdrskin-0.3.5 - 2007.03.16.001311
|
||||||
|
* Usage of /dev/srN rather than /dev/sgN on Linux >= 2.6
|
||||||
|
* New option drive_scsi_dev_family=sr|scd|sg
|
||||||
|
|
||||||
|
|
||||||
|
18 Mar 2007 [777]
|
||||||
|
cdrskin/cdrskin_eng.html
|
||||||
|
Mentioned new sr behavior
|
||||||
|
|
||||||
|
2007.03.24.093238 [785]
|
||||||
|
libburn/drive.c
|
||||||
|
Fixed bug with burn_disc_available_space(...,NULL)
|
||||||
|
|
||||||
|
2007.03.24.093623 [786]
|
||||||
|
cdrskin/cdrskin.c
|
||||||
|
Warning of very small tsize= settings. (Proposal by Eduard Bloch)
|
||||||
|
|
||||||
|
2007.03.27.213543 [787]
|
||||||
|
cdrskin/cdrskin.c
|
||||||
|
cdrskin/cdrfifo.h
|
||||||
|
cdrskin/cdrfifo.c
|
||||||
|
Preparations for option -isosize via fifo (only a debug message yet)
|
||||||
|
|
||||||
|
2007.03.28.100934 [788]
|
||||||
|
libburn/libburn.h
|
||||||
|
libburn/structure.c
|
||||||
|
cdrskin/cdrskin.c
|
||||||
|
Enabled -isosize for first track by help of fifo and without seeking
|
||||||
|
|
||||||
|
2007.03.28.111739 [789]
|
||||||
|
cdrskin/cdrskin.c
|
||||||
|
Silenced error condition about -sao with stdin and -isosize
|
||||||
|
|
||||||
|
2007.03.28.160503 [790]
|
||||||
|
cdrskin/cdrskin.c
|
||||||
|
Enabled -isosize with S_IFREG or S_IFBLK files and without fifo
|
||||||
|
|
||||||
|
2007.03.28.182419 [791]
|
||||||
|
cdrskin/cdrskin.c
|
||||||
|
cdrskin/cdrskin.1
|
||||||
|
Made fifo based -isosize read 64k first and the rest only at normal stage
|
||||||
|
|
||||||
|
2007.03.28.202802 [792]
|
||||||
|
cdrskin/cdrskin.c
|
||||||
|
Silenced error message if tsize= is smaller than source is willing to deliver
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------ cycle - cdrskin-0.3.5 - 2007.03.28.212322
|
||||||
|
* Option -isosize is supported now
|
||||||
|
|
||||||
|
|
||||||
|
29 Mar 2007 [793]
|
||||||
|
cdrskin/cdrskin_eng.html
|
||||||
|
cdrskin/changelog.txt
|
||||||
|
Next cdrskin-0.3.5 cycle
|
||||||
|
|
||||||
|
2007.03.30.201034 [794]
|
||||||
|
libburn/write.c
|
||||||
|
cdrskin/cdrskin.1
|
||||||
|
Allowed finalizing of DVD+R
|
||||||
|
|
||||||
|
2007.03.30.214657 [795]
|
||||||
|
libburn/write.c
|
||||||
|
Avoided unconditional finalizing of DVD+R
|
||||||
|
|
||||||
|
2007.04.03.140356 [796]
|
||||||
|
libburn/sg-linux.c
|
||||||
|
Added fcntl() locking to O_EXCL locking
|
||||||
|
|
||||||
|
2007.04.03.145637 [797]
|
||||||
|
cdrskin/cdrskin.c
|
||||||
|
Make --old_pseudo_scsi_adr -scanbus work with any drive_scsi_dev_family=
|
||||||
|
|
||||||
|
2007.04.03.145806 [798]
|
||||||
|
libburn/libdax_msgs.h
|
||||||
|
Added fcntl() locking to O_EXCL locking
|
||||||
|
|
||||||
|
2007.04.04.184341 [799]
|
||||||
|
libburn/libburn.h
|
||||||
|
libburn/init.c
|
||||||
|
libburn/sg-linux.c
|
||||||
|
cdrskin/cdrskin.c
|
||||||
|
cdrskin/cdrskin.1
|
||||||
|
New cdrskin options --drive_not_f_setlk and --drive_not_o_excl
|
||||||
|
|
||||||
|
6 Apr 2007 [801]
|
||||||
|
test/libburner.c
|
||||||
|
Updated media list in introduction comment
|
||||||
|
|
||||||
|
2007.04.09.105543 [802]
|
||||||
|
libburn/transport.h
|
||||||
|
libburn/os-linux.h
|
||||||
|
libburn/sg-linux.c
|
||||||
|
cdrskin/cdrskin.1
|
||||||
|
Cleaned up scsi sibling management, sketched grafting of DDLP
|
||||||
|
|
||||||
|
2007.04.09.111215 [803]
|
||||||
|
libburn/sg-linux.c
|
||||||
|
Reacted on compiler warning about last_rdev, fixed fresh typo bug
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------ cycle - cdrskin-0.3.5 - 2007.04.09.112127
|
||||||
|
* DVD+R now get finalized (if not -multi is given)
|
||||||
|
|
||||||
|
|
||||||
|
10 Apr 2007 [804]
|
||||||
|
cdrskin/changelog.txt
|
||||||
|
Next cdrskin-0.3.5 cycle
|
||||||
|
|
||||||
|
2007.04.10.081855 [805]
|
||||||
|
libburn/init.c
|
||||||
|
Fixed bug with drive_scsi_dev_family= introduced by revision 796 (fcntl lock)
|
||||||
|
|
||||||
|
2007.04.10.082229 [806]
|
||||||
|
libburn/sg-linux.c
|
||||||
|
Used O_EXCL|O_RDWR and fcntl() even within sg_obtain_scsi_adr()
|
||||||
|
|
||||||
|
2007.04.10.083119 [807]
|
||||||
|
libburn/sg-linux.c
|
||||||
|
Fixed bug in sg_open_scsi_siblings() introduced with revision 802
|
||||||
|
|
||||||
|
2007.04.10.144840 [808]
|
||||||
|
libburn/spc.c
|
||||||
|
libburn/libdax_msgs.h
|
||||||
|
Avoided SIGSEGV with an old SCSI CD-ROM drive and its wild replies
|
||||||
|
|
||||||
|
12 Apr 2007 [810]
|
||||||
|
README
|
||||||
|
Clarified license. People who object shall please come forward now.
|
||||||
|
|
||||||
|
2007.04.13.171347 [815]
|
||||||
|
libburn/sg-linux.c
|
||||||
|
libburn/libdax_msgs.h
|
||||||
|
Switched from O_NONBLOCK to O_NDELAY (see http://lkml.org/lkml/2007/4/11/141)
|
||||||
|
|
||||||
|
2007.04.13.173008 [816]
|
||||||
|
cdrskin/cdrskin.c
|
||||||
|
cdrskin/cdrskin.1
|
||||||
|
Made use of fcntl(F_SETLK) switchable (and thus became more free with default)
|
||||||
|
|
||||||
|
15 Apr 2007 [819]
|
||||||
|
+ libburn/ddlpa.h
|
||||||
|
+ libburn/ddlpa.c
|
||||||
|
Began test implementation of DDLP-A
|
||||||
|
|
||||||
|
15 Apr 2007 [820]
|
||||||
|
libburn/ddlpa.h
|
||||||
|
libburn/ddlpa.c
|
||||||
|
Implemented ddlpa_lock_btl()
|
||||||
|
|
||||||
|
16 Apr 2007 [821]
|
||||||
|
doc/cookbook.txt
|
||||||
|
Finalized DVD+R cookbook
|
||||||
|
|
||||||
|
16 Apr 2007 [822]
|
||||||
|
+ doc/ddlp.txt
|
||||||
|
Emerging description of DDLP
|
||||||
|
|
||||||
|
16 Apr 2007 [823]
|
||||||
|
doc/ddlp.txt
|
||||||
|
libburn/ddlpa.h
|
||||||
|
libburn/ddlpa.c
|
||||||
|
Polished txt and finally threw out getter functions
|
||||||
|
|
||||||
|
16 Apr 2007 [824]
|
||||||
|
libburn/ddlpa.h
|
||||||
|
Corrected description of return values
|
||||||
|
|
||||||
|
18 Apr 2007 [825]
|
||||||
|
+ test/open-cd-excl.c
|
||||||
|
Program for probing access to device files. By Ted Ts'o with modifications by me.
|
||||||
|
|
||||||
|
18 Apr 2007 [826]
|
||||||
|
doc/ddlp.txt
|
||||||
|
Allowed for Friendly Programs: O_EXCL | O_RDONLY
|
||||||
|
|
||||||
|
18 Apr 2007 [827]
|
||||||
|
libburn/ddlpa.h
|
||||||
|
libburn/ddlpa.c
|
||||||
|
Progress due to tests with test/open-cd-excl
|
||||||
|
|
||||||
|
2007.04.18.103734 [828]
|
||||||
|
libburn/mmc.c
|
||||||
|
Updated comments about DVD+R
|
||||||
|
|
||||||
|
18 Apr 2007 [829]
|
||||||
|
test/open-cd-excl.c
|
||||||
|
libburn/ddlpa.c
|
||||||
|
doc/ddlp.txt
|
||||||
|
Polished messages, comments and description of DDLP-A
|
||||||
|
|
||||||
|
18 Apr 2007 [830]
|
||||||
|
test/open-cd-excl.c
|
||||||
|
doc/ddlp.txt
|
||||||
|
Adaptations to new test results and discussions
|
||||||
|
|
||||||
|
18 Apr 2007 [831]
|
||||||
|
doc/ddlp.txt
|
||||||
|
Corrected a list of standard paths
|
||||||
|
|
||||||
|
19 Apr 2007 [832] [833]
|
||||||
|
doc/ddlp.txt
|
||||||
|
Clarifications about motivation and duties of the participants
|
||||||
|
|
||||||
|
20 Apr 2007 [834]
|
||||||
|
doc/ddlp.txt
|
||||||
|
Beginning to develop DDLP-B
|
||||||
|
|
||||||
|
21 Apr 2007 [835]
|
||||||
|
doc/ddlp.txt
|
||||||
|
Declared failure of DDLP to entirely solve the concurrency problem
|
||||||
|
|
||||||
|
------------------------------------ cycle - cdrskin-0.3.5 - 2007.04.22.112236
|
||||||
|
|
||||||
|
22 Apr 2007 [836]
|
||||||
|
cdrskin/changelog.txt
|
||||||
|
Next cdrskin-0.3.5 cycle
|
||||||
|
|
||||||
|
22 Apr 2007 [837]
|
||||||
|
cdrskin/add_ts_changes_to_libburn_0_3_5
|
||||||
|
cdrskin/add_ts_changes_to_libburn_0_3_4
|
||||||
|
Repaired autotools bootstrap bug by help of sed
|
||||||
|
|
||||||
|
22 Apr 2007 [838]
|
||||||
|
cdrskin/cdrskin.1
|
||||||
|
Changed many /dev/sg to /dev/sr
|
||||||
|
|
||||||
|
|
||||||
|
2007.04.23.130001 [tag 841]
|
||||||
|
Makefile.am
|
||||||
|
configure.ac
|
||||||
|
README
|
||||||
|
cdrskin/cdrskin.c
|
||||||
|
cdrskin/README
|
||||||
|
cdrskin/compile_cdrskin.sh
|
||||||
|
cdrskin/cdrskin_timestamp.h
|
||||||
|
cdrskin/wiki_plain.txt
|
||||||
|
cdrskin/cdrskin_eng.html
|
||||||
|
doc/comments
|
||||||
|
Made number transition and activated development documentation
|
||||||
|
|
||||||
|
23 Apr 2007 [tag 842]
|
||||||
|
- cdrskin/add_ts_changes_to_libburn_0_3_4
|
||||||
|
- cdrskin/add_ts_changes_to_libburn_0_3_5
|
||||||
|
+ cdrskin/add_ts_changes_to_libburn_0_3_6
|
||||||
|
+ cdrskin/add_ts_changes_to_libburn_0_3_7
|
||||||
|
Updated cdrskin tarball generator
|
||||||
|
|
||||||
|
23 Apr 2007 [tag 844]
|
||||||
|
cdrskin/README
|
||||||
|
Corrected false info about outdated addressing method
|
||||||
|
|
||||||
|
2007.04.23.154600 [843]
|
||||||
|
Makefile.am
|
||||||
|
configure.ac
|
||||||
|
README
|
||||||
|
cdrskin/cdrskin.c
|
||||||
|
cdrskin/README
|
||||||
|
cdrskin/compile_cdrskin.sh
|
||||||
|
cdrskin/wiki_plain.txt
|
||||||
|
cdrskin/cdrskin_eng.html
|
||||||
|
doc/comments
|
||||||
|
Made number transition and activated development documentation
|
||||||
|
|
||||||
|
23 Apr 2007 [845]
|
||||||
|
- cdrskin/add_ts_changes_to_libburn_0_3_4
|
||||||
|
- cdrskin/add_ts_changes_to_libburn_0_3_5
|
||||||
|
+ cdrskin/add_ts_changes_to_libburn_0_3_6
|
||||||
|
+ cdrskin/add_ts_changes_to_libburn_0_3_7
|
||||||
|
Updated cdrskin tarball generator
|
||||||
|
|
||||||
|
|
||||||
|
----------------------------- release - cdrskin-0.3.6.pl00 - 2007.04.23.130001
|
||||||
|
* Usage of /dev/srN rather than /dev/sgN on Linux >= 2.6
|
||||||
|
* New option drive_scsi_dev_family=sr|scd|sg
|
||||||
|
* Option -isosize is supported now
|
||||||
|
* DVD+R now get finalized (if not -multi is given)
|
||||||
|
|
||||||
|
|
||||||
|
2007.04.23.171735 [846]
|
||||||
|
cdrskin/changelog.txt
|
||||||
|
Next cdrskin-0.3.7 cycle
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------ cycle - cdrskin-0.3.7 - 2007.04.24.113310
|
||||||
|
|
||||||
|
2007.05.21.184334 [853]
|
||||||
|
libburn/sg-linux.c
|
||||||
|
Prepared fflushing and stderr output of SCSI command log
|
||||||
|
|
||||||
|
2007.05.21.185450 [854]
|
||||||
|
libburn/sbc.c
|
||||||
|
libburn/spc.h
|
||||||
|
libburn/spc.c
|
||||||
|
libburn/mmc.c
|
||||||
|
libburn/toc.c
|
||||||
|
libburn/transport.h
|
||||||
|
For Linux 2.4, USB : Carefully avoided to inquire more data than available
|
||||||
|
|
||||||
|
2007.05.21.185644 [855]
|
||||||
|
libburn/sector.c
|
||||||
|
libburn/write.c
|
||||||
|
For Linux 2.4, USB audio : Reduced CD output buffer size to 32 kiB
|
||||||
|
|
||||||
|
21 May 2007 [856]
|
||||||
|
cdrskin/cdrskin_eng.html
|
||||||
|
cdrskin/changelog.txt
|
||||||
|
Next cdrskin-0.3.7 cycle
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------ cycle - cdrskin-0.3.7 - 2007.05.21.201501
|
||||||
|
* Now able to cope with the peculiarities of Linux 2.4 USB
|
||||||
|
|
||||||
|
|
||||||
|
2007.05.22.154407 [857]
|
||||||
|
libburn/sg-linux.c
|
||||||
|
Report eventual sg_io_hdr_t host_status,driver_status as debug messages
|
||||||
|
|
||||||
|
2007.05.22.154504 [858]
|
||||||
|
cdrskin/cdrskin.c
|
||||||
|
Disabled macro Cdrskin_debug_libdax_msgS. Thus getting unqueued error messages.
|
||||||
|
|
||||||
|
2007.05.22.164850 [859]
|
||||||
|
libburn/sg-linux.c
|
||||||
|
Added SCSI opcode to output of revision 857
|
||||||
|
|
||||||
|
2007.05.28.132412 [860]
|
||||||
|
libburn/os-linux.h
|
||||||
|
libburn/write.c
|
||||||
|
Moved general 32 kiB buffer restriction from write.c to os-linux.h
|
||||||
|
|
||||||
|
2007.05.28.165630 [861]
|
||||||
|
libburn/libburn.h
|
||||||
|
libburn/drive.c
|
||||||
|
test/telltoc.c
|
||||||
|
Extended struct burn_multi_caps by .might_simulate
|
||||||
|
|
||||||
|
28 May 2007 [862]
|
||||||
|
libburn/libdax_msgs.h
|
||||||
|
Forgotten update of error list with revison 857
|
||||||
|
|
||||||
|
2007.05.28.170243 [863]
|
||||||
|
libburn/options.c
|
||||||
|
cdrskin/cdrskin.1
|
||||||
|
Added check for .might_simulate to burn_write_opts_auto_write_type()
|
||||||
|
|
||||||
|
2007.05.28.192421 [864]
|
||||||
|
libburn/sector.c
|
||||||
|
Fixed low transaction size introduced by cooperation of revisions 855 and 860
|
||||||
|
|
||||||
|
|
||||||
|
------------------------------------ cycle - cdrskin-0.3.7 - 2007.05.28.192853
|
||||||
|
* Refusal to perform -dummy runs on media which cannot simulate burning
|
||||||
|
|
||||||
|
29 May 2007 [865]
|
||||||
|
cdrskin/cdrskin_eng.html
|
||||||
|
cdrskin/changelog.txt
|
||||||
|
Next cdrskin-0.3.7 cycle
|
||||||
|
|
||||||
|
8 Jun 2007 [873]
|
||||||
|
- cdrskin/doener_150x200_tr.gif
|
||||||
|
- cdrskin/doener_150x200_tr_octx.gif
|
||||||
|
+ cdrskin/doener_150x200_tr.png
|
||||||
|
+ cdrskin/doener_150x200_tr_octx.png
|
||||||
|
cdrskin/cdrskin_eng.html
|
||||||
|
Changed logo graphics format from GIF to PNG
|
||||||
|
|
||||||
|
8 Jun 2007 [874]
|
||||||
|
cdrskin/wiki_plain.txt
|
||||||
|
cdrskin/add_ts_changes_to_libburn_0_3_6
|
||||||
|
cdrskin/add_ts_changes_to_libburn_0_3_7
|
||||||
|
Took into respect change of logo graphics format
|
||||||
|
|
||||||
|
8 Jun 2007 [875]
|
||||||
|
cdrskin/cdrskin.1
|
||||||
|
Prevented macro interpretation of text snippet ".wav"
|
||||||
|
|
||||||
|
10 Jun 2007 [876]
|
||||||
|
cdrskin/README
|
||||||
|
cdrskin/cdrskin.1
|
||||||
|
Clarified MB to MiB if compatibility allows it (ticket 100)
|
||||||
|
|
||||||
|
10 Jun 2007 [877]
|
||||||
|
cdrskin/cdrskin.1
|
||||||
|
doc/cookbook.txt
|
||||||
|
test/libburner.c
|
||||||
|
Changed "KB" to "kiB"
|
||||||
|
|
||||||
|
------------------------------------ cycle - cdrskin-0.3.7 - 2007.06.10.081025
|
||||||
|
|
||||||
|
|
||||||
|
2007.07.12.162856 [882]
|
||||||
|
libburn/transport.h
|
||||||
|
libburn/mmc.c
|
||||||
|
libburn/write.c
|
||||||
|
libburn/libdax_msgs.h
|
||||||
|
Preparations to avoid writing which will not fit in drive buffer
|
||||||
|
|
||||||
|
2007.07.12.171727 [883]
|
||||||
|
libburn/libburn.h
|
||||||
|
libburn/drive.c
|
||||||
|
New API-Function burn_drive_set_buffer_waiting()
|
||||||
|
|
||||||
|
2007.07.12.171832 [884]
|
||||||
|
cdrskin/cdrskin.c
|
||||||
|
cdrskin/cdrskin.1
|
||||||
|
New options modesty_on_drive= and minbuf=
|
||||||
|
|
||||||
|
2007.07.14.111614 [885]
|
||||||
|
libburn/libburn.h
|
||||||
|
libburn/drive.c
|
||||||
|
New API function burn_drive_get_best_speed()
|
||||||
|
|
||||||
|
2007.07.14.112029 [886]
|
||||||
|
libburn/mmc.c
|
||||||
|
Only set realistic maximum DVD speeds (for my LG GSA which fails otherwise)
|
||||||
|
|
||||||
|
2007.07.14.112326 [887]
|
||||||
|
cdrskin/cdrskin.c
|
||||||
|
Experimental option --adjust_speed_to_drive. Caution: May vanish soon.
|
||||||
|
|
||||||
|
17 Jul 2007 [888]
|
||||||
|
cdrskin/cdrskin.1
|
||||||
|
Clarification on option speed=
|
||||||
|
|
||||||
|
2007.07.17.085823 [889]
|
||||||
|
libburn/libburn.h
|
||||||
|
libburn/drive.c
|
||||||
|
libburn/mmc.c
|
||||||
|
cdrskin/cdrskin.c
|
||||||
|
Implemented minimum speed in burn_drive_set_speed()
|
||||||
|
|
||||||
|
2007.07.19.072434 [890]
|
||||||
|
libburn/libburn.h
|
||||||
|
cdrskin/cdrskin.c
|
||||||
|
cdrskin/cdrskin.1
|
||||||
|
Removed ban against speed 0 with burn_drive_set_buffer_waiting()
|
||||||
|
|
||||||
|
2007.07.19.143139 [891]
|
||||||
|
cdrskin/cdrskin.c
|
||||||
|
Trying to prevent usage of burn drive as track source
|
||||||
|
|
||||||
|
2007.07.19.171947 [892]
|
||||||
|
cdrskin/cdrskin.c
|
||||||
|
Avoided new track-drive test with option --no_convert_fs_adr
|
||||||
|
|
||||||
|
19 Jul 2007 [893]
|
||||||
|
cdrskin/cdrskin.1
|
||||||
|
Documented option --adjust_speed_to_drive (i.e. it will stay)
|
||||||
|
|
||||||
|
19 Jul 2007 [894]
|
||||||
|
cdrskin/changelog.txt
|
||||||
|
Next cdrskin-0.3.7 cycle
|
||||||
|
|
||||||
|
19 Jul 2007 [895]
|
||||||
|
cdrskin/cdrskin_eng.html
|
||||||
|
Next cdrskin-0.3.7 cycle
|
||||||
|
|
||||||
|
------------------------------------ cycle - cdrskin-0.3.7 - 2007.07.19.174859
|
||||||
|
* New option modesty_on_drive= may help with hda -> hdb burns
|
||||||
|
* New option minbuf= , cdrecord compatible frontend of modesty_on_drive=
|
||||||
|
* New option --adjust_speed_to_drive
|
||||||
|
* Precautions against using the burner drive as track source
|
||||||
|
|
||||||
|
|
||||||
|
2007.07.20.120001 [branch 897]
|
||||||
|
Makefile.am
|
||||||
|
configure.ac
|
||||||
|
README
|
||||||
|
cdrskin/cdrskin.c
|
||||||
|
cdrskin/README
|
||||||
|
cdrskin/compile_cdrskin.sh
|
||||||
|
cdrskin/cdrskin_timestamp.h
|
||||||
|
cdrskin/cdrskin_eng.html
|
||||||
|
Made number transition to 0.3.8
|
||||||
|
|
||||||
|
20 Jul 2007 [branch 898]
|
||||||
|
- cdrskin/add_ts_changes_to_libburn_0_3_6
|
||||||
|
- cdrskin/add_ts_changes_to_libburn_0_3_7
|
||||||
|
+ cdrskin/add_ts_changes_to_libburn_0_3_8
|
||||||
|
+ cdrskin/add_ts_changes_to_libburn_0_3_9
|
||||||
|
Updated cdrskin tarball generators
|
||||||
|
|
||||||
|
|
||||||
|
----------------------------- release - cdrskin-0.3.8.pl00 - 2007.07.
|
||||||
|
* Now able to cope with the peculiarities of Linux 2.4 USB
|
||||||
|
* Refusal to perform -dummy runs on media which cannot simulate burning
|
||||||
|
* New option modesty_on_drive= may help with hda -> hdb burns
|
||||||
|
* New option minbuf= , cdrecord compatible frontend of modesty_on_drive=
|
||||||
|
* New option --adjust_speed_to_drive
|
||||||
|
* Precautions against using the burner drive as track source
|
||||||
|
|
||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
TODO
|
TODO
|
||||||
===============================================================================
|
===============================================================================
|
||||||
|
|
||||||
------------------------------------ cycle - cdrskin-0.3.3 -
|
------------------------------------ cycle - cdrskin-0.3.7 -
|
||||||
|
cdrskin/changelog.txt
|
||||||
|
Next cdrskin-0.3.7 cycle
|
||||||
|
|
||||||
cdrskin: prevent usage of burn drive as track source
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
What about minimum track sizes ? (POWER OFF/ON , BUS RESET ?)
|
What about minimum track sizes ? (POWER OFF/ON , BUS RESET ?)
|
||||||
|
|
||||||
How to handle finalizing ?
|
|
||||||
growisofs does not finalize multi-session DVD[+-]R unless padding up. Why ?
|
|
||||||
|
|
||||||
Make wide use of mmc_four_char_to_int(), mmc_int_to_four_char()
|
|
||||||
|
|
||||||
Think about cdrecord option minbuf= for simultaneous operation on hdc and hdd
|
|
||||||
|
|
||||||
After cooking: review of -do_diet ?
|
After cooking: review of -do_diet ?
|
||||||
|
|
||||||
@ -3372,23 +3935,14 @@ Disable error checking with DVD-RAM.
|
|||||||
|
|
||||||
Rectify mmc_read_atip speed interpretation. 12x media are reported as 10x. I never heard of 6x media.
|
Rectify mmc_read_atip speed interpretation. 12x media are reported as 10x. I never heard of 6x media.
|
||||||
|
|
||||||
Sequentially check option list for DVD compliance
|
|
||||||
|
|
||||||
|
|
||||||
----------------------------------------- long term intentions:
|
----------------------------------------- long term intentions:
|
||||||
|
|
||||||
[]
|
|
||||||
Ticket 90: failure on USB
|
|
||||||
|
|
||||||
[]
|
[]
|
||||||
-reset: ioctl(fd,CDROMRESET) ioctl(fd,SG_SCSI_RESET,SG_SCSI_RESET_DEVICE)
|
-reset: ioctl(fd,CDROMRESET) ioctl(fd,SG_SCSI_RESET,SG_SCSI_RESET_DEVICE)
|
||||||
http://developer.osdl.org/dev/robustmutexes/src/fusyn.hg/Documentation/ioctl/cdrom.txt
|
http://developer.osdl.org/dev/robustmutexes/src/fusyn.hg/Documentation/ioctl/cdrom.txt
|
||||||
|
|
||||||
|
|
||||||
[]
|
|
||||||
Open O_EXCL all devices in address resolution chain
|
|
||||||
(Might help with non-standard hdX device siblings)
|
|
||||||
|
|
||||||
[]
|
[]
|
||||||
Convert burn_print() into libdax_msgs_submit()
|
Convert burn_print() into libdax_msgs_submit()
|
||||||
|
|
||||||
@ -3402,5 +3956,5 @@ Clear outdated persistent read buffer after small CD image was read (ticket 57)
|
|||||||
|
|
||||||
===============================================================================
|
===============================================================================
|
||||||
This is the dirty end of the todo list.
|
This is the dirty end of the todo list.
|
||||||
For most recent changelog entries scroll up about 100 lines.
|
The recent changelog entries are above the headline "TODO".
|
||||||
===============================================================================
|
===============================================================================
|
||||||
|
@ -7,7 +7,7 @@
|
|||||||
debug_opts=
|
debug_opts=
|
||||||
def_opts=
|
def_opts=
|
||||||
largefile_opts="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1"
|
largefile_opts="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1"
|
||||||
libvers="-DCdrskin_libburn_0_3_4"
|
libvers="-DCdrskin_libburn_0_3_8"
|
||||||
cleanup_src_or_obj="libburn/cleanup.o"
|
cleanup_src_or_obj="libburn/cleanup.o"
|
||||||
libdax_msgs_o="libburn/libdax_msgs.o"
|
libdax_msgs_o="libburn/libdax_msgs.o"
|
||||||
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
|
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
|
||||||
@ -33,15 +33,15 @@ do
|
|||||||
libdax_audioxtr_o=
|
libdax_audioxtr_o=
|
||||||
libdax_msgs_o="libburn/message.o"
|
libdax_msgs_o="libburn/message.o"
|
||||||
cleanup_src_or_obj="-DCleanup_has_no_libburn_os_H cdrskin/cleanup.c"
|
cleanup_src_or_obj="-DCleanup_has_no_libburn_os_H cdrskin/cleanup.c"
|
||||||
elif test "$i" = "-libburn_0_3_4"
|
elif test "$i" = "-libburn_0_3_8"
|
||||||
then
|
then
|
||||||
libvers="-DCdrskin_libburn_0_3_4"
|
libvers="-DCdrskin_libburn_0_3_8"
|
||||||
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
|
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
|
||||||
libdax_msgs_o="libburn/libdax_msgs.o"
|
libdax_msgs_o="libburn/libdax_msgs.o"
|
||||||
cleanup_src_or_obj="libburn/cleanup.o"
|
cleanup_src_or_obj="libburn/cleanup.o"
|
||||||
elif test "$i" = "-libburn_svn"
|
elif test "$i" = "-libburn_svn"
|
||||||
then
|
then
|
||||||
libvers="-DCdrskin_libburn_0_3_5"
|
libvers="-DCdrskin_libburn_0_3_9"
|
||||||
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
|
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
|
||||||
libdax_msgs_o="libburn/libdax_msgs.o"
|
libdax_msgs_o="libburn/libdax_msgs.o"
|
||||||
cleanup_src_or_obj="libburn/cleanup.o"
|
cleanup_src_or_obj="libburn/cleanup.o"
|
||||||
@ -79,7 +79,7 @@ do
|
|||||||
echo " -compile_cdrfifo compile program cdrskin/cdrfifo."
|
echo " -compile_cdrfifo compile program cdrskin/cdrfifo."
|
||||||
echo " -compile_dewav compile program test/dewav without libburn."
|
echo " -compile_dewav compile program test/dewav without libburn."
|
||||||
echo " -cvs_A60220 set macro to match libburn-CVS of 20 Feb 2006."
|
echo " -cvs_A60220 set macro to match libburn-CVS of 20 Feb 2006."
|
||||||
echo " -libburn_0_3_4 set macro to match libburn-0.3.4."
|
echo " -libburn_0_3_8 set macro to match libburn-0.3.8."
|
||||||
echo " -libburn_svn set macro to match current libburn-SVN."
|
echo " -libburn_svn set macro to match current libburn-SVN."
|
||||||
echo " -no_largefile do not use 64 bit off_t (must match libburn)."
|
echo " -no_largefile do not use 64 bit off_t (must match libburn)."
|
||||||
echo " -do_not_compile_cdrskin omit compilation of cdrskin/cdrskin."
|
echo " -do_not_compile_cdrskin omit compilation of cdrskin/cdrskin."
|
||||||
|
Binary file not shown.
Before Width: | Height: | Size: 34 KiB |
BIN
cdrskin/doener_150x200_tr.png
Normal file
BIN
cdrskin/doener_150x200_tr.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
Binary file not shown.
Before Width: | Height: | Size: 29 KiB |
BIN
cdrskin/doener_150x200_tr_octx.png
Normal file
BIN
cdrskin/doener_150x200_tr_octx.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.2 KiB |
@ -1,7 +1,7 @@
|
|||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
cdrskin Wiki - plain text copy
|
cdrskin Wiki - plain text copy
|
||||||
--------------------------------------------------------------------------
|
--------------------------------------------------------------------------
|
||||||
[[Image(source:/libburn/trunk/cdrskin/doener_150x200_tr.gif)]] [http://en.wikipedia.org/wiki/D%C3%B6ner_kebab Doener]
|
[[Image(source:/libburn/trunk/cdrskin/doener_150x200_tr.png)]] [http://en.wikipedia.org/wiki/D%C3%B6ner_kebab Doener]
|
||||||
|
|
||||||
'''cdrskin is the cdrecord compatibility middleware of libburn.'''
|
'''cdrskin is the cdrecord compatibility middleware of libburn.'''
|
||||||
|
|
||||||
@ -67,7 +67,7 @@ and displays their detected properties.
|
|||||||
The drives are listed one per line, with fields:
|
The drives are listed one per line, with fields:
|
||||||
libburn-drive-number, sysadmin-device-file, permissions, vendor, type
|
libburn-drive-number, sysadmin-device-file, permissions, vendor, type
|
||||||
{{{
|
{{{
|
||||||
0 dev='/dev/sg0' rwrw-- : 'HL-DT-ST' 'DVDRAM GSA-4082B'
|
0 dev='/dev/sr0' rwrw-- : 'HL-DT-ST' 'DVDRAM GSA-4082B'
|
||||||
}}}
|
}}}
|
||||||
This feature is valuable since cdrskin -scanbus will not give you
|
This feature is valuable since cdrskin -scanbus will not give you
|
||||||
the device file name and its current permissions.
|
the device file name and its current permissions.
|
||||||
@ -127,7 +127,7 @@ E.g. cdrskin aborts with an error message if
|
|||||||
{{{
|
{{{
|
||||||
assert_write_lba=0
|
assert_write_lba=0
|
||||||
}}}
|
}}}
|
||||||
is given but an appendable media is to be burned which would start ati
|
is given but an appendable media is to be burned which would start at
|
||||||
block 68432.
|
block 68432.
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,4 +1,4 @@
|
|||||||
AC_INIT([libburn], [0.3.4], [http://libburnia.pykix.org])
|
AC_INIT([libburn], [0.3.8], [http://libburnia.pykix.org])
|
||||||
AC_PREREQ([2.50])
|
AC_PREREQ([2.50])
|
||||||
dnl AC_CONFIG_HEADER([config.h])
|
dnl AC_CONFIG_HEADER([config.h])
|
||||||
|
|
||||||
@ -19,7 +19,7 @@ dnl if MAJOR or MINOR version changes, be sure to change AC_INIT above to match
|
|||||||
dnl
|
dnl
|
||||||
BURN_MAJOR_VERSION=0
|
BURN_MAJOR_VERSION=0
|
||||||
BURN_MINOR_VERSION=3
|
BURN_MINOR_VERSION=3
|
||||||
BURN_MICRO_VERSION=4
|
BURN_MICRO_VERSION=8
|
||||||
BURN_INTERFACE_AGE=0
|
BURN_INTERFACE_AGE=0
|
||||||
BURN_BINARY_AGE=0
|
BURN_BINARY_AGE=0
|
||||||
BURN_VERSION=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION
|
BURN_VERSION=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION
|
||||||
@ -33,7 +33,7 @@ AC_SUBST(BURN_VERSION)
|
|||||||
|
|
||||||
dnl Libtool versioning
|
dnl Libtool versioning
|
||||||
LT_RELEASE=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION
|
LT_RELEASE=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION
|
||||||
LT_CURRENT=`expr $BURN_MICRO_VERSION - $BURN_INTERFACE_AGE`
|
LT_CURRENT=4
|
||||||
LT_REVISION=$BURN_INTERFACE_AGE
|
LT_REVISION=$BURN_INTERFACE_AGE
|
||||||
LT_AGE=`expr $BURN_BINARY_AGE - $BURN_INTERFACE_AGE`
|
LT_AGE=`expr $BURN_BINARY_AGE - $BURN_INTERFACE_AGE`
|
||||||
LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
|
LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
|
||||||
|
@ -33,7 +33,7 @@ scope by help of existing cdrecord frontends.
|
|||||||
|
|
||||||
- libburn is the library by which preformatted data get onto optical media.
|
- libburn is the library by which preformatted data get onto optical media.
|
||||||
It uses either /dev/sgN (e.g. on kernel 2.4 with ide-scsi) or
|
It uses either /dev/sgN (e.g. on kernel 2.4 with ide-scsi) or
|
||||||
/dev/hdX (e.g. on kernel 2.6).
|
/dev/srM or /dev/hdX (e.g. on kernel 2.6).
|
||||||
libburn is the foundation of our cdrecord emulation. Its code is
|
libburn is the foundation of our cdrecord emulation. Its code is
|
||||||
independent of cdrecord. Its DVD capabilities are learned from
|
independent of cdrecord. Its DVD capabilities are learned from
|
||||||
studying the code of dvd+rw-tools and MMC-5 specs. No code but only
|
studying the code of dvd+rw-tools and MMC-5 specs. No code but only
|
||||||
|
@ -5,7 +5,7 @@ Content:
|
|||||||
- SAO CD Cookbook (CD-R, CD-RW, pure audio or pure data only)
|
- SAO CD Cookbook (CD-R, CD-RW, pure audio or pure data only)
|
||||||
- Overwriteable DVD Cookbook (DVD-RAM, DVD+RW, DVD-RW)
|
- Overwriteable DVD Cookbook (DVD-RAM, DVD+RW, DVD-RW)
|
||||||
- Sequential DVD-R[W] Cookbook
|
- Sequential DVD-R[W] Cookbook
|
||||||
- DVD+R Cookbook (still emerging)
|
- DVD+R Cookbook
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
TAO Multi-Session CD Cookbook
|
TAO Multi-Session CD Cookbook
|
||||||
@ -788,12 +788,12 @@ growisofs (transport.hxx) sets Link Size to 16 for profiles 0011h and 0014h.
|
|||||||
libburn now records the first link size from feature 0021h in its burn_drive
|
libburn now records the first link size from feature 0021h in its burn_drive
|
||||||
structure. If another link size item is 16, then 16 is used.
|
structure. If another link size item is 16, then 16 is used.
|
||||||
[*4:]
|
[*4:]
|
||||||
growisofs takes Packet Size from 52h. Specs predict it will be 16 (= 32 kB).
|
growisofs takes Packet Size from 52h. Specs predict it will be 16 (= 32 kiB).
|
||||||
(mmc5r03.pdf 7.5.4.16)
|
(mmc5r03.pdf 7.5.4.16)
|
||||||
|
|
||||||
The writing process is much like in "Writing a session to CD in TAO mode" :
|
The writing process is much like in "Writing a session to CD in TAO mode" :
|
||||||
Next Writeable Address is fetched from the reply of 52h READ TRACK INFORMATION.
|
Next Writeable Address is fetched from the reply of 52h READ TRACK INFORMATION.
|
||||||
libburn writes full 32 kB buffers via 2Ah WRITE.
|
libburn writes full 32 kiB buffers via 2Ah WRITE.
|
||||||
(mmc5r03c.pdf, 6.27 READ TRACK INFORMATION, 6.44 WRITE)
|
(mmc5r03c.pdf, 6.27 READ TRACK INFORMATION, 6.44 WRITE)
|
||||||
When writing is done, it is mandatory to force the drive's buffer to media by
|
When writing is done, it is mandatory to force the drive's buffer to media by
|
||||||
35h SYNCHRONIZE CACHE.
|
35h SYNCHRONIZE CACHE.
|
||||||
@ -860,7 +860,8 @@ tested yet, what happens if not enough data get written.
|
|||||||
(mmc5r03c.pdf 6.31)
|
(mmc5r03c.pdf 6.31)
|
||||||
|
|
||||||
Next Writeable Address is fetched from the reply of 52h READ TRACK INFORMATION.
|
Next Writeable Address is fetched from the reply of 52h READ TRACK INFORMATION.
|
||||||
The reply is supposed to be 0. libburn writes full 32 kB buffers via 2Ah WRITE.
|
The reply is supposed to be 0. libburn writes full 32 kiB buffers via
|
||||||
|
2Ah WRITE.
|
||||||
(mmc5r03c.pdf, 6.27 READ TRACK INFORMATION, 6.44 WRITE)
|
(mmc5r03c.pdf, 6.27 READ TRACK INFORMATION, 6.44 WRITE)
|
||||||
If the track source delivers less than the announced size then libburn pads up
|
If the track source delivers less than the announced size then libburn pads up
|
||||||
by zeros.
|
by zeros.
|
||||||
@ -1063,7 +1064,7 @@ The specs promise to pad up the track if not enough data get written.
|
|||||||
Next Writeable Address is fetched from the reply of 52h READ TRACK INFORMATION
|
Next Writeable Address is fetched from the reply of 52h READ TRACK INFORMATION
|
||||||
with track number FFh.
|
with track number FFh.
|
||||||
(mmc5r03c.pdf 6.27)
|
(mmc5r03c.pdf 6.27)
|
||||||
Since the fixely set write type is 16-block packet, full 32 kB buffers have
|
Since the fixely set write type is 16-block packet, full 32 kiB buffers have
|
||||||
to be transmitted via 2Ah WRITE.
|
to be transmitted via 2Ah WRITE.
|
||||||
(mmc5r03c.pdf 4.3.6.2.2)
|
(mmc5r03c.pdf 4.3.6.2.2)
|
||||||
|
|
||||||
@ -1078,17 +1079,17 @@ libburn obtains the necessary logical track number from Last Track Number in
|
|||||||
Last Session from the reply of 51h READ DISC INFORMATION requesting
|
Last Session from the reply of 51h READ DISC INFORMATION requesting
|
||||||
Data Type 000b.
|
Data Type 000b.
|
||||||
(mmc5r03c.pdf 6.22)
|
(mmc5r03c.pdf 6.22)
|
||||||
|
|
||||||
After each track 5Bh CLOSE TRACK SESSION Close Function 010b with Logical Track
|
After each track 5Bh CLOSE TRACK SESSION Close Function 010b with Logical Track
|
||||||
Number 0 closes the DVD+R session but keeps the media appendable.
|
Number 0 closes the DVD+R session but keeps the media appendable.
|
||||||
(mmc5r03c.pdf 6.3.3.4.3)
|
(mmc5r03c.pdf 6.3.3.4.3)
|
||||||
|
If the media shall not stay appendable then the last DVD+R session is to be
|
||||||
|
closed by Close Function 101b rather than 010b. This finalizes the media
|
||||||
>>> This is not tested yet. growisofs has code for that gesture but explicitly
|
"with minimal radius".
|
||||||
avoids to use it. Instead it recommends to fill up the media with zeros.
|
|
||||||
Eventually 5Bh CLOSE TRACK SESSION Close Function 101b is used to finalize
|
|
||||||
the media with minimal radius. After that the disc is not appendable any more !
|
|
||||||
(mmc5r03c.pdf 6.3.3.4.4)
|
(mmc5r03c.pdf 6.3.3.4.4)
|
||||||
|
|
||||||
|
Note: growisofs has code for that gesture but explicitly avoids to use it.
|
||||||
|
Instead it recommends to fill up the media with zeros.
|
||||||
|
|
||||||
-------------------------------------------------------------------------------
|
-------------------------------------------------------------------------------
|
||||||
Hearsay about DVD+R/DL (Dual Layer) :
|
Hearsay about DVD+R/DL (Dual Layer) :
|
||||||
|
388
doc/ddlp.txt
Normal file
388
doc/ddlp.txt
Normal file
@ -0,0 +1,388 @@
|
|||||||
|
-------------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Users of modern desktop Linux installations report misburns with CD/DVD
|
||||||
|
recording due to concurrency problems.
|
||||||
|
|
||||||
|
This text describes two locking protocols which have been developed by our
|
||||||
|
best possible effort. But finally they rather serve as repelling example of
|
||||||
|
what would be needed in user space to achieve an insufficient partial solution.
|
||||||
|
|
||||||
|
Ted Ts'o was so friendly to help as critic with his own use cases. It turned
|
||||||
|
out that we cannot imagine a way in user space how to cover reliably the needs
|
||||||
|
of callers of libblkid and the needs of our burn programs.
|
||||||
|
|
||||||
|
-------------------------------------------------------------------------------
|
||||||
|
Content:
|
||||||
|
|
||||||
|
The "Delicate Device Locking Protocol" shall demonstrate our sincere
|
||||||
|
consideration of the problem.
|
||||||
|
|
||||||
|
"What are the Stumble Stones ?" lists reasons why the effort finally failed.
|
||||||
|
|
||||||
|
-----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
|
||||||
|
Delicate Device Locking Protocol
|
||||||
|
(a joint sub project of cdrkit and libburnia)
|
||||||
|
(contact: scdbackup@gmx.net )
|
||||||
|
|
||||||
|
Our projects provide programs which allow recording of data on CD or DVD.
|
||||||
|
We encounter an increasing number of bug reports about spoiled burn runs and
|
||||||
|
wasted media which obviously have one common cause: interference by other
|
||||||
|
programs which access the drive's device files.
|
||||||
|
There is some riddling about which gestures exactly are dangerous for
|
||||||
|
ongoing recordings or can cause weirdly misformatted drive replies to MMC
|
||||||
|
commands.
|
||||||
|
We do know, nevertheless, that these effects do not occur if no other program
|
||||||
|
accesses a device file of the drive while our programs use it.
|
||||||
|
|
||||||
|
DDLP shall help to avoid collisions between programs in the process of
|
||||||
|
recording to a CD or DVD drive and other programs which access that drive.
|
||||||
|
The protocol intends to provide advisory locking. So any good-willing program
|
||||||
|
has to take some extra precautions to participate.
|
||||||
|
|
||||||
|
If a program does not feel vulnerable to disturbance, then the precautions
|
||||||
|
impose much less effort than if the program feels the need for protection.
|
||||||
|
|
||||||
|
Two locking strategies are specified:
|
||||||
|
DDLP-A operates on device files only. It is very Linux specific.
|
||||||
|
DDLP-B adds proxy lock files, inspired by FHS /var/lock standard.
|
||||||
|
|
||||||
|
|
||||||
|
DDLP-A
|
||||||
|
|
||||||
|
This protocol relies on the hardly documented feature open(O_EXCL | O_RDWR)
|
||||||
|
with Linux device files and on POSIX compliant fcntl(F_SETLK).
|
||||||
|
|
||||||
|
Other than the original meaning of O_EXCL with creating regular files, the
|
||||||
|
effect on device files is mutual exclusion of access. I.e. if one
|
||||||
|
filedescriptor is open on that combination of major-minor device number, then
|
||||||
|
no other open(O_EXCL) will succeed. But open() without O_EXCL would succeed.
|
||||||
|
So this is advisory and exclusive locking.
|
||||||
|
With kernel 2.6 it seems to work on all device drivers which might get used
|
||||||
|
to access a CD/DVD drive.
|
||||||
|
|
||||||
|
The vulnerable programs shall not start their operation before they occupied a
|
||||||
|
wide collection of drive representations.
|
||||||
|
Non-vulnerable programs shall take care to detect the occupation of _one_ such
|
||||||
|
representation.
|
||||||
|
|
||||||
|
So for Friendly Programs
|
||||||
|
|
||||||
|
A program which does not feel vulnerable to disturbance is urged to access
|
||||||
|
CD/DVD drives by opening a file descriptor which will uphold the lock
|
||||||
|
as long as it does not get closed. There are two alternative ways to achieve
|
||||||
|
this.
|
||||||
|
Very reliable is
|
||||||
|
|
||||||
|
open( some_path , O_EXCL | ...)
|
||||||
|
|
||||||
|
But O_EXCL imposes restrictions and interferences:
|
||||||
|
- O_EXCL | O_RDONLY does not succeed with /dev/sg* !
|
||||||
|
- O_EXCL cannot provide shared locks for programs which only want to lock
|
||||||
|
against burn programs but not against their own peers.
|
||||||
|
- O_EXCL keeps from obtaining information by harmless activities.
|
||||||
|
- O_EXCL already has a meaning with devices which are mounted as filesystems.
|
||||||
|
This priority meaning is more liberal than the one needed for CD/DV recording
|
||||||
|
protection.
|
||||||
|
|
||||||
|
So it may be necessary to use a cautious open() without O_EXCL and to aquire
|
||||||
|
a POSIX lock via fcntl(). "Cautious" means to add O_NDELAY to the flags of
|
||||||
|
open(), because this is declared to avoid side effects within open().
|
||||||
|
|
||||||
|
With this gesture it is important to use the paths expected by our burn
|
||||||
|
programs: /dev/sr[0..255] /dev/scd[0..255] /dev/sg[0..255] /dev/hd[a..z]
|
||||||
|
because fcntl(F_SETLK) does not lock the device but only a device-inode.
|
||||||
|
|
||||||
|
std_path = one of the standard device files:
|
||||||
|
/dev/sr[0..255] /dev/scd[0..255] /dev/sg[0..255] /dev/hd[a..z]
|
||||||
|
or a symbolic link pointing to one of them.
|
||||||
|
open( std_path , ... | O_NDELAY)
|
||||||
|
fcntl(F_SETLK) and close() on failure
|
||||||
|
... eventually disable O_NDELAY by fcntl(F_SETFL) ...
|
||||||
|
|
||||||
|
There is a pitfall mentioned in man 2 fcntl :
|
||||||
|
"locks are automatically released [...] if it closes any file descriptor
|
||||||
|
referring to a file on which locks are held. This is bad [...]"
|
||||||
|
So you may have to re-lock after some temporary fd got closed.
|
||||||
|
|
||||||
|
|
||||||
|
Vulnerable Programs
|
||||||
|
|
||||||
|
For programs which do feel vulnerable, O_EXCL would suffice for the /dev/hd*
|
||||||
|
device file family and their driver. But USB and SATA recorders appear with
|
||||||
|
at least two different major-minor combinations simultaneously.
|
||||||
|
One as /dev/sr* alias /dev/scd*, the other as /dev/sg*.
|
||||||
|
The same is true for ide-scsi or recorders attached to SCSI controllers.
|
||||||
|
|
||||||
|
So, in order to lock any access to the recorder, one has to open(O_EXCL)
|
||||||
|
not only the device file that is intended for accessing the recorder but also
|
||||||
|
a device file of any other major-minor representation of the recorder.
|
||||||
|
This is done via the SCSI address parameter vector (Host,Channel,Id,Lun)
|
||||||
|
and a search on standard device file paths /dev/sr* /dev/scd* /dev/sg*.
|
||||||
|
In this text the alternative device representations are called "siblings".
|
||||||
|
|
||||||
|
For finding them, it is necessary to apply open() to many device files which
|
||||||
|
might be occupied by delicate operations. On the other hand it is very
|
||||||
|
important to occupy all reasonable representations of the drive.
|
||||||
|
So the reading of the (Host,Channel,Id,Lun) parameters demands an
|
||||||
|
open(O_RDONLY | O_NDELAY) _without_ fcntl() in order to find the outmost
|
||||||
|
number of representations among the standard device files. Only ioctls
|
||||||
|
SCSI_IOCTL_GET_IDLUN and SCSI_IOCTL_GET_BUS_NUMBER are applied.
|
||||||
|
Hopefully this gesture is unable to cause harmful side effects on kernel 2.6.
|
||||||
|
|
||||||
|
At least one file of each class sr, scd and sg should be found to regard
|
||||||
|
the occupation as satisfying. Thus corresponding sr-scd-sg triplets should have
|
||||||
|
matching ownerships and access permissions.
|
||||||
|
One will have to help the sysadmins to find those triplets.
|
||||||
|
|
||||||
|
A spicy detail is that sr and scd may be distinct device files for the same
|
||||||
|
major-minor combination. In this case fcntl() locks on both are needed
|
||||||
|
but O_EXCL can only be applied to one of them.
|
||||||
|
|
||||||
|
|
||||||
|
An open and free implementation ddlpa.[ch] is provided as
|
||||||
|
http://libburnia.pykix.org/browser/libburn/trunk/libburn/ddlpa.h?format=txt
|
||||||
|
http://libburnia.pykix.org/browser/libburn/trunk/libburn/ddlpa.c?format=txt
|
||||||
|
The current version of this text is
|
||||||
|
http://libburnia.pykix.org/browser/libburn/trunk/doc/ddlp.txt?format=txt
|
||||||
|
|
||||||
|
Put ddlpa.h and ddlpa.c into the same directory and compile as test program by
|
||||||
|
cc -g -Wall -DDDLPA_C_STANDALONE -o ddlpa ddlpa.c
|
||||||
|
|
||||||
|
Use it to occupy a drive's representations for a given number of seconds
|
||||||
|
./ddlpa /dev/sr0 300
|
||||||
|
|
||||||
|
It should do no harm to any of your running activities.
|
||||||
|
If it does: Please, please alert us.
|
||||||
|
|
||||||
|
Your own programs should not be able to circumvent the occupation if they
|
||||||
|
obey above rules for Friendly Programs.
|
||||||
|
Of course ./ddlpa should be unable to circumvent itself.
|
||||||
|
|
||||||
|
A successfull occupation looks like
|
||||||
|
DDLPA_DEBUG: ddlpa_std_by_rdev("/dev/scd0") = "/dev/sr0"
|
||||||
|
DDLPA_DEBUG: ddlpa_collect_siblings() found "/dev/sr0"
|
||||||
|
DDLPA_DEBUG: ddlpa_collect_siblings() found "/dev/scd0"
|
||||||
|
DDLPA_DEBUG: ddlpa_collect_siblings() found "/dev/sg0"
|
||||||
|
DDLPA_DEBUG: ddlpa_occupy() : '/dev/scd0'
|
||||||
|
DDLPA_DEBUG: ddlpa_occupy() O_EXCL : '/dev/sg0'
|
||||||
|
DDLPA_DEBUG: ddlpa_occupy() O_EXCL : '/dev/sr0'
|
||||||
|
---------------------------------------------- Lock gained
|
||||||
|
ddlpa: opened /dev/sr0
|
||||||
|
ddlpa: opened siblings: /dev/scd0 /dev/sg0
|
||||||
|
slept 1 seconds of 300
|
||||||
|
|
||||||
|
Now an attempt via device file alias /dev/NEC must fail:
|
||||||
|
DDLPA_DEBUG: ddlpa_std_by_rdev("/dev/NEC") = "/dev/sg0"
|
||||||
|
DDLPA_DEBUG: ddlpa_collect_siblings() found "/dev/sr0"
|
||||||
|
DDLPA_DEBUG: ddlpa_collect_siblings() found "/dev/scd0"
|
||||||
|
DDLPA_DEBUG: ddlpa_collect_siblings() found "/dev/sg0"
|
||||||
|
Cannot exclusively open '/dev/sg0'
|
||||||
|
Reason given : Failed to open O_RDWR | O_NDELAY | O_EXCL : '/dev/sr0'
|
||||||
|
Error condition : 16 'Device or resource busy'
|
||||||
|
|
||||||
|
With hdc, of course, things are trivial
|
||||||
|
DDLPA_DEBUG: ddlpa_std_by_rdev("/dev/hdc") = "/dev/hdc"
|
||||||
|
DDLPA_DEBUG: ddlpa_occupy() O_EXCL : '/dev/hdc'
|
||||||
|
---------------------------------------------- Lock gained
|
||||||
|
ddlpa: opened /dev/hdc
|
||||||
|
slept 1 seconds of 1
|
||||||
|
|
||||||
|
|
||||||
|
Ted Ts'o provided program open-cd-excl which allows to explore open(2) on
|
||||||
|
device files with combinations of read-write, O_EXCL, and fcntl().
|
||||||
|
(This does not mean that Ted endorsed our project yet. He helps exploring.)
|
||||||
|
|
||||||
|
Friendly in the sense of DDLP-A would be any run which uses at least one of
|
||||||
|
the options -e (i.e. O_EXCL) or -f (i.e. F_SETLK, applied to a file
|
||||||
|
descriptor which was obtained from a standard device file path).
|
||||||
|
The code is available under GPL at
|
||||||
|
http://libburnia.pykix.org/browser/libburn/trunk/test/open-cd-excl.c?format=txt
|
||||||
|
To be compiled by
|
||||||
|
cc -g -Wall -o open-cd-excl open-cd-excl.c
|
||||||
|
|
||||||
|
Options:
|
||||||
|
-e : open O_EXCL
|
||||||
|
-f : aquire lock by fcntl(F_SETLK) after sucessful open
|
||||||
|
-i : do not wait in case of success but exit 0 immediately
|
||||||
|
-r : open O_RDONLY , with -f use F_RDLCK
|
||||||
|
-w : open O_RDWR , with -f use F_WRLCK
|
||||||
|
plus the path of the devce file to open.
|
||||||
|
|
||||||
|
Friendly Programs would use gestures like:
|
||||||
|
./open-cd-excl -e -r /dev/sr0
|
||||||
|
./open-cd-excl -e -w /dev/sg1
|
||||||
|
./open-cd-excl -e -w /dev/black-drive
|
||||||
|
./open-cd-excl -f -r /dev/sg1
|
||||||
|
./open-cd-excl -e -f -w /dev/sr0
|
||||||
|
|
||||||
|
Ignorant programs would use and cause potential trouble by:
|
||||||
|
./open-cd-excl -r /dev/sr0
|
||||||
|
./open-cd-excl -w /dev/sg1
|
||||||
|
./open-cd-excl -f -w /dev/black-drive
|
||||||
|
where "/dev/black-drive" is _not_ a symbolic link to
|
||||||
|
any of /dev/sr* /dev/scd* /dev/sg* /dev/hd*, but has an own inode.
|
||||||
|
|
||||||
|
Prone to failure without further reason is:
|
||||||
|
./open-cd-excl -e -r /dev/sg1
|
||||||
|
|
||||||
|
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
DDLP-B
|
||||||
|
|
||||||
|
This protocol relies on proxy lock files in some filesystem directory. It can
|
||||||
|
be embedded into DDLP-A or it can be used be used standalone, outside DDLP-A.
|
||||||
|
|
||||||
|
DDLP-A shall be kept by DDLP-B from trying to access any device file which
|
||||||
|
might already be in use. There is a problematic gesture in DDLP-A when SCSI
|
||||||
|
address parameters are to be retrieved. For now this gesture seems to be
|
||||||
|
harmless. But one never knows.
|
||||||
|
Vice versa DDLP-B may get from DDLP-A the service to search for SCSI device
|
||||||
|
file siblings. So they are best as a couple.
|
||||||
|
|
||||||
|
But they are not perfect. Not even as couple. fcntl() locking is flawed.
|
||||||
|
|
||||||
|
|
||||||
|
There is a proxy file locking protocol described in FHS:
|
||||||
|
http://www.pathname.com/fhs/pub/fhs-2.3.html#VARLOCKLOCKFILES
|
||||||
|
|
||||||
|
But it has shortcommings (see below). Decisive obstacle for its usage are the
|
||||||
|
possibility for stale locks and the lack of shared locks.
|
||||||
|
|
||||||
|
DDLP-B rather defines a "path prefix" which is advised to be
|
||||||
|
/tmp/ddlpb-lock-
|
||||||
|
This prefix will get appended "device specific suffixes" and then form the path
|
||||||
|
of a "lockfile".
|
||||||
|
Not the existence of a lockfile but its occupation by an fcntl(F_SETLK) will
|
||||||
|
constitute a lock. Lockfiles may get prepared by the sysadmin in directories
|
||||||
|
where normal users are not allowed to create new files. Their rw-permissions
|
||||||
|
then act as additional access restriction to the device files.
|
||||||
|
The use of fcntl(F_SETLK) will prevent any stale locks after the process ended.
|
||||||
|
It will also allow to obtain shared locks as well as exclusive locks.
|
||||||
|
|
||||||
|
There are two classes of device specific suffixes:
|
||||||
|
|
||||||
|
- Device file path suffix. Absolute paths only. "/" gets replaced by "_-".
|
||||||
|
Eventual "_-" in path gets replaced by "_-_-". The leading group of "_-"
|
||||||
|
is always interpreted as a group of "/", though. E.g.:
|
||||||
|
/dev/sr0 <-> "_-dev_-sr0"
|
||||||
|
/mydevs/burner/nec <-> "_-mydevs_-burners_-nec"
|
||||||
|
/dev/rare_-name <-> "_-dev_-rare_-_-name"
|
||||||
|
///strange/dev/x <-> "_-_-_-strange_-dev_-x"
|
||||||
|
|
||||||
|
- st_rdev suffix. A hex representation of struct stat.st_rdev. Capital letters.
|
||||||
|
The number of characters is pare with at most one leading 0. I.e. bytewise
|
||||||
|
printf("%2.2X") beginning with the highest order byte that is not zero.
|
||||||
|
E.g. : "0B01", "2200", "01000000000004001"
|
||||||
|
|
||||||
|
If a lockfile does not exist and cannot be created then this shall not keep
|
||||||
|
a program from working on a device. But if a lockfile exists and if permissions
|
||||||
|
or locking state do not allow to obtain a lock of the appropirate type, then
|
||||||
|
this shall prevent any opening of device file in question resp. shall cause
|
||||||
|
immediate close(2) of an already opened device file.
|
||||||
|
|
||||||
|
The vulnerable programs shall not start their operation before they locked a
|
||||||
|
wide collection of drive representations.
|
||||||
|
|
||||||
|
Non-vulnerable programs shall take care to lock the suffix resulting from the
|
||||||
|
path they will be using and the suffix from the st_rdev from that path.
|
||||||
|
The latter is to be obtained by call stat(2).
|
||||||
|
|
||||||
|
Locks get upheld as long as their file descriptor is not closed or no other
|
||||||
|
incident as described in man 2 fcntl releases the lock.
|
||||||
|
|
||||||
|
So with shared locks there are no imandatory further activities after they
|
||||||
|
have been obtained.
|
||||||
|
|
||||||
|
In case of exclusive locks, the file has to have been opened for writing and
|
||||||
|
must be truncated to 0 bytes length immediately after obtaining the lock.
|
||||||
|
When releasing an exclusive lock it is a nice gesture to
|
||||||
|
already do this truncation.
|
||||||
|
Then a /var/lock/ compatible first line has to be written.
|
||||||
|
E.g. by: printf("%10u\n",(unsigned) getpid()) yielding " 1230\n".
|
||||||
|
|
||||||
|
Any further lines are optional. They shall have the form Name=Value and must
|
||||||
|
be printable cleartext. If such further lines exist, then the last one must
|
||||||
|
have the name "endmark".
|
||||||
|
Defined Names are:
|
||||||
|
hostid =hostname of the machine where the process number of line 1 is valid
|
||||||
|
start =start time of lock in seconds since 1970. E.g: 1177147634.592410
|
||||||
|
program =self chosen name of the program which obtained the lock
|
||||||
|
argv0 =argv[0] of that program
|
||||||
|
mainpath =device file path which will be used for operations by that program
|
||||||
|
path =device file path which lead to the lock
|
||||||
|
st_rdev =st_rdev suffix which is associated with path
|
||||||
|
scsi_hcil=eventual SCSI parameters Host,Channel,Id,Lun
|
||||||
|
scsi_bus =eventual SCSI parameter Bus
|
||||||
|
endmark =declares the info as complete.
|
||||||
|
Any undefined name or a line without "=" shall be handled as comment.
|
||||||
|
"=" in the value is allowed. Any line beginning with an "=" character is an
|
||||||
|
extension of the previous value.
|
||||||
|
|
||||||
|
If programs encounter an exclusive lock, they are invited to read the content
|
||||||
|
of the lockfile anyway. But they should be aware that the info might be in the
|
||||||
|
progress of emerging. There is a race condition possible in the short time
|
||||||
|
between obtaining the exclusive lock and erasing the file content.
|
||||||
|
If it is not crucial to obtain most accurate info then one may take the newline
|
||||||
|
of the first line as indicator of a valid process number and the "endmark"
|
||||||
|
name as indicator that the preceding lines are valid.
|
||||||
|
Very cautious readers should obtain the info twice with a decent waiting period
|
||||||
|
inbetween. Only if both results are identical they should be considered valid.
|
||||||
|
|
||||||
|
|
||||||
|
There is no implementation of DDLP-B yet.
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
What are the Stumble Stones ?
|
||||||
|
----------------------------------------------------------------------------
|
||||||
|
|
||||||
|
Any of the considered locking mechanisms has decisive shortcommings
|
||||||
|
which keeps it from being the solution to all known legitimate use cases.
|
||||||
|
|
||||||
|
The attempt has failed to compose a waterproof locking mechanism from means of
|
||||||
|
POSIX, FHS and from hardly documented Linux open(O_EXCL) on device files.
|
||||||
|
The resulting mechanisms would need about 1000 lines of code and still do
|
||||||
|
not close all gaps resp. cover the well motivated use cases.
|
||||||
|
This attempt you see above: DDLP-A and DDLP-B.
|
||||||
|
|
||||||
|
|
||||||
|
Summary of the reasons why the established locking mechanisms do not suffice:
|
||||||
|
|
||||||
|
None of the mechanisms can take care of the double device driver identity
|
||||||
|
sr versus sg. To deduce the one device file from the other involves the need
|
||||||
|
to open many other (possibly unrelated) device files with the risk to disturb
|
||||||
|
them.
|
||||||
|
This hard to solve problem is aggravated by the following facts.
|
||||||
|
|
||||||
|
Shortcommings of Linux specific open(O_EXCL) :
|
||||||
|
|
||||||
|
- O_EXCL | O_RDONLY does not succeed with /dev/sg*
|
||||||
|
- O_EXCL cannot provide shared locks for programs which only want to lock
|
||||||
|
against burn programs but not against their own peers.
|
||||||
|
- O_EXCL keeps from obtaining information by harmless activities.
|
||||||
|
- O_EXCL already has a meaning with devices which are mounted as filesystems.
|
||||||
|
This priority meaning is more liberal than the one needed for CD/DV recording
|
||||||
|
protection.
|
||||||
|
|
||||||
|
Shortcommings of POSIX fcntl(F_SETLK) :
|
||||||
|
|
||||||
|
- fcntl() demands an open file descriptor. open(2) might have side effects.
|
||||||
|
- fcntl() locks can be released inadvertedly by submodules which just open and
|
||||||
|
close the same file (inode ?) without refering to fcntl locks in any way.
|
||||||
|
See man 2 fcntl "This is bad:".
|
||||||
|
Stacking of software modules is a widely used design pattern. But fcntl()
|
||||||
|
cannot cope with that.
|
||||||
|
|
||||||
|
Shortcommings of FHS /var/lock/ :
|
||||||
|
|
||||||
|
- Stale locks are possible.
|
||||||
|
- It is necessary to create a file (using the _old_ meaning of O_EXCL flag ?)
|
||||||
|
but /var/lock/ might not be available early during system start and it often
|
||||||
|
has restrictive permission settings.
|
||||||
|
- There is no way to indicate a difference between exclusive and shared locks.
|
||||||
|
- The FHS prescription relies entirely on the basename of the device file path.
|
||||||
|
|
614
libburn/ddlpa.c
Normal file
614
libburn/ddlpa.c
Normal file
@ -0,0 +1,614 @@
|
|||||||
|
|
||||||
|
/* ddlpa
|
||||||
|
Implementation of Delicate Device Locking Protocol level A.
|
||||||
|
Copyright (C) 2007 Thomas Schmitt <scdbackup@gmx.net>
|
||||||
|
Provided under any of the following licenses: GPL, LGPL, BSD. Choose one.
|
||||||
|
|
||||||
|
|
||||||
|
Compile as test program:
|
||||||
|
|
||||||
|
cc -g -Wall \
|
||||||
|
-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1 -D_LARGEFILE64_SOURCE \
|
||||||
|
-DDDLPA_C_STANDALONE -o ddlpa ddlpa.c
|
||||||
|
|
||||||
|
The system macros enable 64-bit off_t and open(2) flag O_LARGEFILE, which
|
||||||
|
are not absolutely necessary but explicitely take into respect that
|
||||||
|
our devices can offer more than 2 GB of addressable data.
|
||||||
|
|
||||||
|
Run test program:
|
||||||
|
|
||||||
|
./ddlpa /dev/sr0 15
|
||||||
|
./ddlpa 0,0,0 15
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <errno.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/ioctl.h>
|
||||||
|
#include <scsi/scsi.h>
|
||||||
|
|
||||||
|
|
||||||
|
/* All callers of ddlpa must do this */
|
||||||
|
#include "ddlpa.h"
|
||||||
|
|
||||||
|
|
||||||
|
/* 1 = Enable progress message on stderr, 0 = normal silent operation */
|
||||||
|
static int ddlpa_debug_mode = 1;
|
||||||
|
|
||||||
|
|
||||||
|
/* #define _GNU_SOURCE or _LARGEFILE64_SOURCE to get real O_LARGEFILE */
|
||||||
|
#ifndef O_LARGEFILE
|
||||||
|
#define O_LARGEFILE 0
|
||||||
|
#endif
|
||||||
|
|
||||||
|
|
||||||
|
/* ----------------------- private -------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
static int ddlpa_new(struct ddlpa_lock **lck, int o_flags, int ddlpa_flags)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
struct ddlpa_lock *o;
|
||||||
|
|
||||||
|
o = *lck = (struct ddlpa_lock *) malloc(sizeof(struct ddlpa_lock));
|
||||||
|
if (o == NULL)
|
||||||
|
return ENOMEM;
|
||||||
|
for (i = 0; i < sizeof(struct ddlpa_lock); i++)
|
||||||
|
((char *) o)[i] = 0;
|
||||||
|
o->path = NULL;
|
||||||
|
o->fd = -1;
|
||||||
|
for (i = 0; i < DDLPA_MAX_SIBLINGS; i++)
|
||||||
|
o->sibling_fds[i] = -1;
|
||||||
|
o->errmsg = NULL;
|
||||||
|
|
||||||
|
o->o_flags = o_flags;
|
||||||
|
o->ddlpa_flags = ddlpa_flags;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int ddlpa_enumerate(struct ddlpa_lock *o, int *idx,
|
||||||
|
char path[DDLPA_MAX_STD_LEN + 1])
|
||||||
|
{
|
||||||
|
if (*idx < 0)
|
||||||
|
*idx = 0;
|
||||||
|
|
||||||
|
if (*idx < 26)
|
||||||
|
sprintf(path, "/dev/hd%c", 'a' + *idx);
|
||||||
|
else if (*idx < 256 + 26)
|
||||||
|
sprintf(path, "/dev/sr%d", *idx - 26);
|
||||||
|
else if (*idx < 2 * 256 + 26)
|
||||||
|
sprintf(path, "/dev/scd%d", *idx - 256 - 26);
|
||||||
|
else if (*idx < 3 * 256 + 26)
|
||||||
|
sprintf(path, "/dev/sg%d", *idx - 2 * 256 - 26);
|
||||||
|
else
|
||||||
|
return 1;
|
||||||
|
(*idx)++;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int ddlpa_std_by_rdev(struct ddlpa_lock *o)
|
||||||
|
{
|
||||||
|
int idx = 0;
|
||||||
|
char try_path[DDLPA_MAX_STD_LEN+1];
|
||||||
|
struct stat path_stbuf, try_stbuf;
|
||||||
|
|
||||||
|
if (!o->path_is_valid)
|
||||||
|
return EFAULT;
|
||||||
|
if (stat(o->path, &path_stbuf) == -1)
|
||||||
|
return errno;
|
||||||
|
|
||||||
|
while (ddlpa_enumerate(o, &idx, try_path) == 0) {
|
||||||
|
if (stat(try_path, &try_stbuf) == -1)
|
||||||
|
continue;
|
||||||
|
if (path_stbuf.st_rdev != try_stbuf.st_rdev)
|
||||||
|
continue;
|
||||||
|
strcpy(o->std_path, try_path);
|
||||||
|
|
||||||
|
if (ddlpa_debug_mode)
|
||||||
|
fprintf(stderr,
|
||||||
|
"DDLPA_DEBUG: ddlpa_std_by_rdev(\"%s\") = \"%s\"\n",
|
||||||
|
o->path, o->std_path);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
return ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Caution : these tests are valid only with standard paths */
|
||||||
|
|
||||||
|
static int ddlpa_is_scsi(struct ddlpa_lock *o, char *path)
|
||||||
|
{
|
||||||
|
return (strncmp(path, "/dev/s", 6) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ddlpa_is_sg(struct ddlpa_lock *o, char *path)
|
||||||
|
{
|
||||||
|
return (strncmp(path, "/dev/sg", 7) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ddlpa_is_sr(struct ddlpa_lock *o, char *path)
|
||||||
|
{
|
||||||
|
return (strncmp(path, "/dev/sr", 7) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static int ddlpa_is_scd(struct ddlpa_lock *o, char *path)
|
||||||
|
{
|
||||||
|
return (strncmp(path, "/dev/scd", 8) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int ddlpa_fcntl_lock(struct ddlpa_lock *o, int fd, int l_type)
|
||||||
|
{
|
||||||
|
struct flock lockthing;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
memset(&lockthing, 0, sizeof(lockthing));
|
||||||
|
lockthing.l_type = l_type;
|
||||||
|
lockthing.l_whence = SEEK_SET;
|
||||||
|
lockthing.l_start = 0;
|
||||||
|
lockthing.l_len = 0;
|
||||||
|
ret = fcntl(fd, F_SETLK, &lockthing);
|
||||||
|
if (ret == -1)
|
||||||
|
return EBUSY;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int ddlpa_occupy(struct ddlpa_lock *o, char *path, int *fd,
|
||||||
|
int no_o_excl)
|
||||||
|
{
|
||||||
|
int ret, o_flags, o_rw, l_type;
|
||||||
|
char *o_rwtext;
|
||||||
|
|
||||||
|
o_flags = o->o_flags | O_NDELAY;
|
||||||
|
if(!no_o_excl)
|
||||||
|
o_flags |= O_EXCL;
|
||||||
|
o_rw = (o_flags) & (O_RDONLY | O_WRONLY | O_RDWR);
|
||||||
|
o_rwtext = (o_rw == O_RDONLY ? "O_RDONLY" :
|
||||||
|
(o_rw == O_WRONLY ? "O_WRONLY" :
|
||||||
|
(o_rw == O_RDWR ? "O_RDWR " : "O_?rw-mode?")));
|
||||||
|
|
||||||
|
*fd = open(path, o_flags);
|
||||||
|
if (*fd == -1) {
|
||||||
|
o->errmsg = malloc(strlen(path)+160);
|
||||||
|
if (o->errmsg)
|
||||||
|
sprintf(o->errmsg,
|
||||||
|
"Failed to open %s | O_NDELAY %s: '%s'",
|
||||||
|
o_rwtext,
|
||||||
|
(o_flags & O_EXCL ? "| O_EXCL " : ""), path);
|
||||||
|
return (errno ? errno : EBUSY);
|
||||||
|
}
|
||||||
|
if (o_rw == O_RDWR || o_rw == O_WRONLY)
|
||||||
|
l_type = F_WRLCK;
|
||||||
|
else
|
||||||
|
l_type = F_RDLCK;
|
||||||
|
ret = ddlpa_fcntl_lock(o, *fd, l_type);
|
||||||
|
if (ret) {
|
||||||
|
o->errmsg = malloc(strlen(path)+160);
|
||||||
|
if (o->errmsg)
|
||||||
|
sprintf(o->errmsg,
|
||||||
|
"Failed to lock fcntl(F_WRLCK) : '%s'",path);
|
||||||
|
close(*fd);
|
||||||
|
*fd = -1;
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
if (ddlpa_debug_mode)
|
||||||
|
fprintf(stderr, "DDLPA_DEBUG: ddlpa_occupy() %s %s: '%s'\n",
|
||||||
|
o_rwtext,
|
||||||
|
(no_o_excl ? " " : "O_EXCL "), path);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int ddlpa_obtain_scsi_adr(struct ddlpa_lock *o, char *path,
|
||||||
|
int *bus, int *host, int *channel, int *id, int *lun)
|
||||||
|
{
|
||||||
|
int fd, ret, open_mode = O_RDONLY | O_NDELAY;
|
||||||
|
struct my_scsi_idlun {
|
||||||
|
int x;
|
||||||
|
int host_unique_id;
|
||||||
|
};
|
||||||
|
struct my_scsi_idlun idlun;
|
||||||
|
|
||||||
|
fd = open(path, open_mode);
|
||||||
|
if (fd == -1)
|
||||||
|
return (errno ? errno : EBUSY);
|
||||||
|
if (ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, bus) == -1)
|
||||||
|
*bus = -1;
|
||||||
|
ret = ioctl(fd, SCSI_IOCTL_GET_IDLUN, &idlun);
|
||||||
|
close(fd);
|
||||||
|
if (ret == -1)
|
||||||
|
return (errno ? errno : EIO);
|
||||||
|
*host = (idlun.x >> 24) & 255;
|
||||||
|
*channel = (idlun.x >> 16) & 255;
|
||||||
|
*id = (idlun.x) & 255;
|
||||||
|
*lun = (idlun.x >> 8 ) & 255;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int ddlpa_collect_siblings(struct ddlpa_lock *o)
|
||||||
|
{
|
||||||
|
int idx = 0, ret, have_sg = 0, have_sr = 0, have_scd = 0;
|
||||||
|
dev_t path_dev;
|
||||||
|
ino_t path_inode;
|
||||||
|
struct stat stbuf;
|
||||||
|
char *path, try_path[DDLPA_MAX_STD_LEN+1];
|
||||||
|
int t_bus, t_host, t_channel, t_id, t_lun;
|
||||||
|
|
||||||
|
if (o->ddlpa_flags & DDLPA_OPEN_GIVEN_PATH)
|
||||||
|
path = o->path;
|
||||||
|
else
|
||||||
|
path = o->std_path;
|
||||||
|
if (path[0] == 0 || o->num_siblings != 0)
|
||||||
|
return EFAULT;
|
||||||
|
if (!ddlpa_is_scsi(o, o->std_path))
|
||||||
|
return EFAULT;
|
||||||
|
|
||||||
|
if (stat(path, &stbuf) == -1)
|
||||||
|
return errno;
|
||||||
|
path_inode = stbuf.st_ino;
|
||||||
|
path_dev = stbuf.st_dev;
|
||||||
|
o->rdev = stbuf.st_rdev;
|
||||||
|
o->dev = stbuf.st_dev;
|
||||||
|
o->ino = stbuf.st_ino;
|
||||||
|
ret = ddlpa_obtain_scsi_adr(o, path,
|
||||||
|
&(o->bus), &(o->host), &(o->channel),
|
||||||
|
&(o->id), &(o->lun));
|
||||||
|
if (ret) {
|
||||||
|
o->errmsg = strdup(
|
||||||
|
"Cannot obtain SCSI parameters host,channel,id,lun");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
o->hcilb_is_valid = 1;
|
||||||
|
|
||||||
|
while (ddlpa_enumerate(o, &idx, try_path) == 0) {
|
||||||
|
if (!ddlpa_is_scsi(o, try_path))
|
||||||
|
continue;
|
||||||
|
if (stat(try_path, &stbuf) == -1)
|
||||||
|
continue;
|
||||||
|
ret = ddlpa_obtain_scsi_adr(o, try_path,
|
||||||
|
&t_bus, &t_host, &t_channel, &t_id, &t_lun);
|
||||||
|
if (ret) {
|
||||||
|
|
||||||
|
/* >>> interpret error, memorize busy, no permission */
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (t_host != o->host || t_channel != o->channel ||
|
||||||
|
t_id != o->id || t_lun != o->lun)
|
||||||
|
continue;
|
||||||
|
|
||||||
|
if (o->num_siblings >= DDLPA_MAX_SIBLINGS) {
|
||||||
|
o->errmsg =
|
||||||
|
strdup("Too many matching device files found");
|
||||||
|
return ERANGE;
|
||||||
|
}
|
||||||
|
if (ddlpa_is_sg(o, try_path))
|
||||||
|
have_sg = 1;
|
||||||
|
else if (ddlpa_is_sr(o, try_path))
|
||||||
|
have_sr = 1;
|
||||||
|
else if (ddlpa_is_scd(o, try_path))
|
||||||
|
have_scd = 1;
|
||||||
|
strcpy(o->sibling_paths[o->num_siblings], try_path);
|
||||||
|
o->sibling_rdevs[o->num_siblings] = stbuf.st_rdev;
|
||||||
|
o->sibling_devs[o->num_siblings] = stbuf.st_dev;
|
||||||
|
o->sibling_inodes[o->num_siblings] = stbuf.st_ino;
|
||||||
|
|
||||||
|
if (ddlpa_debug_mode)
|
||||||
|
fprintf(stderr,
|
||||||
|
"DDLPA_DEBUG: ddlpa_collect_siblings() found \"%s\"\n",
|
||||||
|
try_path);
|
||||||
|
|
||||||
|
(o->num_siblings)++;
|
||||||
|
}
|
||||||
|
if (have_sg && have_sr && have_scd)
|
||||||
|
return 0;
|
||||||
|
if (o->ddlpa_flags & DDLPA_ALLOW_MISSING_SGRCD)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
o->errmsg = strdup("Did not find enough siblings");
|
||||||
|
|
||||||
|
/* >>> add more info about busy and forbidden paths */
|
||||||
|
|
||||||
|
return EBUSY;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int ddlpa_std_by_btl(struct ddlpa_lock *o)
|
||||||
|
{
|
||||||
|
int idx = 0, ret;
|
||||||
|
char try_path[DDLPA_MAX_STD_LEN+1];
|
||||||
|
int t_bus, t_host, t_channel, t_id, t_lun;
|
||||||
|
|
||||||
|
if (!o->inbtl_is_valid)
|
||||||
|
return EFAULT;
|
||||||
|
|
||||||
|
while (ddlpa_enumerate(o, &idx, try_path) == 0) {
|
||||||
|
if (!ddlpa_is_sr(o, try_path))
|
||||||
|
continue;
|
||||||
|
ret = ddlpa_obtain_scsi_adr(o, try_path,
|
||||||
|
&t_bus, &t_host, &t_channel, &t_id, &t_lun);
|
||||||
|
if (ret) {
|
||||||
|
|
||||||
|
/* >>> interpret error, memorize busy, no permission */
|
||||||
|
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
if (t_bus != o->in_bus || t_id != o->in_target ||
|
||||||
|
t_lun != o->in_lun)
|
||||||
|
continue;
|
||||||
|
strcpy(o->std_path, try_path);
|
||||||
|
|
||||||
|
if (ddlpa_debug_mode)
|
||||||
|
fprintf(stderr,
|
||||||
|
"DDLPA_DEBUG: ddlpa_std_by_btl(%d,%d,%d) = \"%s\"\n",
|
||||||
|
t_bus, t_id, t_lun, o->std_path);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* >>> add more info about busy and forbidden paths */
|
||||||
|
|
||||||
|
return ENOENT;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
static int ddlpa_open_all(struct ddlpa_lock *o)
|
||||||
|
{
|
||||||
|
int i, j, ret, no_o_excl;
|
||||||
|
|
||||||
|
if (ddlpa_is_scsi(o, o->std_path)) {
|
||||||
|
ret = ddlpa_collect_siblings(o);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
for (i = 0; i < o->num_siblings; i++) {
|
||||||
|
|
||||||
|
/* Watch out for the main personality of the drive. */
|
||||||
|
/* No need to occupy identical path or softlink path */
|
||||||
|
if (o->sibling_devs[i] == o->dev &&
|
||||||
|
o->sibling_inodes[i] == o->ino)
|
||||||
|
continue;
|
||||||
|
/* There may be the same rdev but different inode. */
|
||||||
|
no_o_excl = (o->sibling_rdevs[i] == o->rdev);
|
||||||
|
|
||||||
|
/* Look for multiply registered device drivers with
|
||||||
|
distinct inodes. */
|
||||||
|
for (j = 0; j < i; j++) {
|
||||||
|
if (o->sibling_devs[j] == o->sibling_devs[i] &&
|
||||||
|
o->sibling_inodes[j] == o->sibling_inodes[i])
|
||||||
|
break;
|
||||||
|
if (o->sibling_rdevs[j] == o->sibling_rdevs[i])
|
||||||
|
no_o_excl = 1;
|
||||||
|
}
|
||||||
|
if (j < i)
|
||||||
|
continue; /* inode is already occupied */
|
||||||
|
|
||||||
|
ret = ddlpa_occupy(o, o->sibling_paths[i],
|
||||||
|
&(o->sibling_fds[i]), no_o_excl);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (o->ddlpa_flags & DDLPA_OPEN_GIVEN_PATH)
|
||||||
|
ret = ddlpa_occupy(o, o->path, &(o->fd), 0);
|
||||||
|
else
|
||||||
|
ret = ddlpa_occupy(o, o->std_path, &(o->fd), 0);
|
||||||
|
if (ret)
|
||||||
|
return ret;
|
||||||
|
|
||||||
|
/* >>> use fcntl() to adjust O_NONBLOCK */;
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ----------------------- public -------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
int ddlpa_destroy(struct ddlpa_lock **lockbundle)
|
||||||
|
{
|
||||||
|
struct ddlpa_lock *o;
|
||||||
|
int i;
|
||||||
|
|
||||||
|
o= *lockbundle;
|
||||||
|
if (o == NULL)
|
||||||
|
return 0;
|
||||||
|
for (i = 0; i < o->num_siblings; i++)
|
||||||
|
if (o->sibling_fds[i] != -1)
|
||||||
|
close(o->sibling_fds[i]);
|
||||||
|
if(o->fd != -1)
|
||||||
|
close(o->fd);
|
||||||
|
if (o->path != NULL)
|
||||||
|
free(o->path);
|
||||||
|
if (o->errmsg != NULL)
|
||||||
|
free(o->errmsg);
|
||||||
|
free((char *) o);
|
||||||
|
*lockbundle = NULL;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ddlpa_lock_path(char *path, int o_flags, int ddlpa_flags,
|
||||||
|
struct ddlpa_lock **lockbundle, char **errmsg)
|
||||||
|
{
|
||||||
|
struct ddlpa_lock *o;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
*errmsg = NULL;
|
||||||
|
if (ddlpa_new(&o, o_flags, ddlpa_flags))
|
||||||
|
return ENOMEM;
|
||||||
|
*lockbundle = o;
|
||||||
|
|
||||||
|
o->path = strdup(path);
|
||||||
|
if (o->path == NULL)
|
||||||
|
return ENOMEM;
|
||||||
|
o->path_is_valid = 1;
|
||||||
|
|
||||||
|
ret = ddlpa_std_by_rdev(o);
|
||||||
|
if (ret) {
|
||||||
|
*errmsg = strdup(
|
||||||
|
"Cannot find equivalent of given path among standard paths");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ret = ddlpa_open_all(o);
|
||||||
|
if (ret) {
|
||||||
|
*errmsg = o->errmsg;
|
||||||
|
o->errmsg = NULL;
|
||||||
|
ddlpa_destroy(&o);
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int ddlpa_lock_btl(int bus, int target, int lun,
|
||||||
|
int o_flags, int ddlpa_flags,
|
||||||
|
struct ddlpa_lock **lockbundle, char **errmsg)
|
||||||
|
{
|
||||||
|
struct ddlpa_lock *o;
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
*errmsg = NULL;
|
||||||
|
ddlpa_flags &= ~DDLPA_OPEN_GIVEN_PATH;
|
||||||
|
if (ddlpa_new(&o, o_flags, ddlpa_flags))
|
||||||
|
return ENOMEM;
|
||||||
|
*lockbundle = o;
|
||||||
|
|
||||||
|
o->in_bus = bus;
|
||||||
|
o->in_target = target;
|
||||||
|
o->in_lun = lun;
|
||||||
|
o->inbtl_is_valid = 1;
|
||||||
|
ret = ddlpa_std_by_btl(o);
|
||||||
|
if (ret) {
|
||||||
|
*errmsg = strdup(
|
||||||
|
"Cannot find /dev/sr* with given Bus,Target,Lun");
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
ret = ddlpa_open_all(o);
|
||||||
|
if (ret) {
|
||||||
|
*errmsg = o->errmsg;
|
||||||
|
o->errmsg = NULL;
|
||||||
|
ddlpa_destroy(&o);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#ifdef DDLPA_C_STANDALONE
|
||||||
|
|
||||||
|
/* ----------------------------- Test / Demo -------------------------- */
|
||||||
|
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct ddlpa_lock *lck = NULL;
|
||||||
|
char *errmsg = NULL, *opened_path = NULL, *my_path = NULL;
|
||||||
|
int i, ret, fd = -1, duration = -1, bus = -1, target = -1, lun = -1;
|
||||||
|
|
||||||
|
if (argc < 3) {
|
||||||
|
usage:;
|
||||||
|
fprintf(stderr, "usage: %s device_path duration\n", argv[0]);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
my_path = argv[1];
|
||||||
|
sscanf(argv[2], "%d", &duration);
|
||||||
|
if (duration < 0)
|
||||||
|
goto usage;
|
||||||
|
|
||||||
|
|
||||||
|
/* For our purpose, only O_RDWR is a suitable access mode.
|
||||||
|
But in order to allow experiments, o_flags are freely adjustable.
|
||||||
|
|
||||||
|
Warning: Do _not_ set an own O_EXCL flag with the following calls !
|
||||||
|
|
||||||
|
(This freedom to fail may get removed in a final version.)
|
||||||
|
*/
|
||||||
|
if (my_path[0] != '/' && my_path[0] != '.' &&
|
||||||
|
strchr(my_path, ',') != NULL) {
|
||||||
|
/*
|
||||||
|
cdrecord style dev=Bus,Target,Lun
|
||||||
|
*/
|
||||||
|
|
||||||
|
sscanf(my_path, "%d,%d,%d", &bus, &target, &lun);
|
||||||
|
ret = ddlpa_lock_btl(bus, target, lun, O_RDWR | O_LARGEFILE,
|
||||||
|
0, &lck, &errmsg);
|
||||||
|
} else {
|
||||||
|
/*
|
||||||
|
This substitutes for:
|
||||||
|
fd = open(my_path, O_RDWR | O_EXCL | O_LARGEFILE);
|
||||||
|
|
||||||
|
*/
|
||||||
|
|
||||||
|
ret = ddlpa_lock_path(my_path, O_RDWR | O_LARGEFILE,
|
||||||
|
0, &lck, &errmsg);
|
||||||
|
}
|
||||||
|
if (ret) {
|
||||||
|
fprintf(stderr, "Cannot exclusively open '%s'\n", my_path);
|
||||||
|
if (errmsg != NULL)
|
||||||
|
fprintf(stderr, "Reason given : %s\n",
|
||||||
|
errmsg);
|
||||||
|
free(errmsg);
|
||||||
|
fprintf(stderr, "Error condition : %d '%s'\n",
|
||||||
|
ret, strerror(ret));
|
||||||
|
exit(2);
|
||||||
|
}
|
||||||
|
fd = lck->fd;
|
||||||
|
|
||||||
|
printf("---------------------------------------------- Lock gained\n");
|
||||||
|
|
||||||
|
|
||||||
|
/* Use fd for the usual operations on the device depicted by my_path.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/* This prints an overview of the impact of the lock */
|
||||||
|
if (lck->ddlpa_flags & DDLPA_OPEN_GIVEN_PATH)
|
||||||
|
opened_path = lck->path;
|
||||||
|
else
|
||||||
|
opened_path = lck->std_path;
|
||||||
|
printf("ddlpa: opened %s", opened_path);
|
||||||
|
|
||||||
|
if (strcmp(opened_path, lck->std_path) != 0)
|
||||||
|
printf(" (an alias of '%s')", lck->std_path);
|
||||||
|
printf("\n");
|
||||||
|
if (lck->num_siblings > 0) {
|
||||||
|
printf("ddlpa: opened siblings:");
|
||||||
|
for (i = 0; i < lck->num_siblings; i++)
|
||||||
|
if (lck->sibling_fds[i] != -1)
|
||||||
|
printf(" %s", lck->sibling_paths[i]);
|
||||||
|
printf("\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* This example waits a while. So other lock candidates can collide. */
|
||||||
|
for (i = 0; i < duration; i++) {
|
||||||
|
sleep(1);
|
||||||
|
fprintf(stderr, "\rslept %d seconds of %d", i + 1, duration);
|
||||||
|
}
|
||||||
|
fprintf(stderr, "\n");
|
||||||
|
|
||||||
|
|
||||||
|
/* When finally done with the drive, this substitutes for:
|
||||||
|
close(fd);
|
||||||
|
*/
|
||||||
|
if (ddlpa_destroy(&lck)) {
|
||||||
|
/* Well, man 2 close says it can fail. */
|
||||||
|
exit(3);
|
||||||
|
}
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* DDLPA_C_STANDALONE */
|
||||||
|
|
107
libburn/ddlpa.h
Normal file
107
libburn/ddlpa.h
Normal file
@ -0,0 +1,107 @@
|
|||||||
|
|
||||||
|
/* ddlpa
|
||||||
|
Implementation of Delicate Device Locking Protocol level A.
|
||||||
|
Copyright (C) 2007 Thomas Schmitt <scdbackup@gmx.net>
|
||||||
|
Provided under any of the following licenses: GPL, LGPL, BSD. Choose one.
|
||||||
|
|
||||||
|
See ../doc/ddlp.txt for a description of the protocol.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef DDLPA_H_INCLUDED
|
||||||
|
#define DDLPA_H_INCLUDED 1
|
||||||
|
|
||||||
|
|
||||||
|
/* An upper limit for the length of standard paths and sibling paths */
|
||||||
|
#define DDLPA_MAX_STD_LEN 15
|
||||||
|
|
||||||
|
/* An upper limit for the number of siblings */
|
||||||
|
#define DDLPA_MAX_SIBLINGS 5
|
||||||
|
|
||||||
|
struct ddlpa_lock {
|
||||||
|
|
||||||
|
/* Recorded input parameters of locking call */
|
||||||
|
char *path;
|
||||||
|
int path_is_valid;
|
||||||
|
int in_bus, in_target, in_lun;
|
||||||
|
int inbtl_is_valid;
|
||||||
|
int ddlpa_flags;
|
||||||
|
int o_flags;
|
||||||
|
|
||||||
|
/* Result of locking call */
|
||||||
|
char std_path[DDLPA_MAX_STD_LEN + 1];
|
||||||
|
int fd;
|
||||||
|
dev_t rdev;
|
||||||
|
dev_t dev;
|
||||||
|
ino_t ino;
|
||||||
|
int host, channel, id, lun, bus;
|
||||||
|
int hcilb_is_valid;
|
||||||
|
int num_siblings;
|
||||||
|
char sibling_paths[DDLPA_MAX_SIBLINGS][DDLPA_MAX_STD_LEN + 1];
|
||||||
|
int sibling_fds[DDLPA_MAX_SIBLINGS];
|
||||||
|
dev_t sibling_rdevs[DDLPA_MAX_SIBLINGS];
|
||||||
|
dev_t sibling_devs[DDLPA_MAX_SIBLINGS];
|
||||||
|
ino_t sibling_inodes[DDLPA_MAX_SIBLINGS];
|
||||||
|
|
||||||
|
/* Is NULL if all goes well. Else it may contain a text message. */
|
||||||
|
char *errmsg;
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Lock a recorder by naming a device file path. Allocate a new container.
|
||||||
|
@param path Gives the file system path of the recorder
|
||||||
|
as known to the calling program.
|
||||||
|
@param o_flags flags for open(2). Do not use O_EXCL here because this
|
||||||
|
is done automatically whenever appropriate.
|
||||||
|
Advised is O_RDWR | O_LARGEFILE, eventually | O_NDELAY.
|
||||||
|
@param ddlpa_flags 0 = default behavior: the standard path will be opened
|
||||||
|
and treated by fcntl(F_SETLK)
|
||||||
|
DDLPA_OPEN_GIVEN_PATH causes the input parameter "path"
|
||||||
|
to be used with open(2) and fcntl(2).
|
||||||
|
DDLPA_ALLOW_MISSING_SGRCD allows to grant a lock
|
||||||
|
although not all three, a sg, a sr and a scd device
|
||||||
|
file have been found during sibling search. Normally
|
||||||
|
this is counted as failure due to EBUSY.
|
||||||
|
@param lockbundle gets allocated and then represents the locking state
|
||||||
|
@param errmsg if *errmsg is not NULL after the call, it contains an
|
||||||
|
error message. Then to be released by free(3).
|
||||||
|
It is NULL in case of success or lack of memory.
|
||||||
|
@return 0=success , else an errno compatible error number
|
||||||
|
*/
|
||||||
|
int ddlpa_lock_path(char *path, int o_flags, int ddlpa_flags,
|
||||||
|
struct ddlpa_lock **lockbundle, char **errmsg);
|
||||||
|
|
||||||
|
|
||||||
|
/** Lock a recorder by naming a Bus,Target,Lun number triple.
|
||||||
|
Allocate a new container.
|
||||||
|
@param bus parameter to match ioctl(SCSI_IOCTL_GET_BUS_NUMBER)
|
||||||
|
@param target parameter to match ioctl(SCSI_IOCTL_GET_IDLUN) &0xff
|
||||||
|
@param lun parameter to match ioctl(SCSI_IOCTL_GET_IDLUN) &0xff00
|
||||||
|
@param o_flags see ddlpa_lock_path().
|
||||||
|
@param ddlpa_flags see ddlpa_lock_path(). Flag DDLPA_OPEN_GIVEN_PATH
|
||||||
|
will be ignored.
|
||||||
|
@param lockbundle see ddlpa_lock_path().
|
||||||
|
@param errmsg see ddlpa_lock_path().
|
||||||
|
@return 0=success , else an errno compatible error number
|
||||||
|
*/
|
||||||
|
int ddlpa_lock_btl(int bus, int target, int lun,
|
||||||
|
int o_flags, int ddlpa_flags,
|
||||||
|
struct ddlpa_lock **lockbundle, char **errmsg);
|
||||||
|
|
||||||
|
|
||||||
|
/** Release the lock by closing all filedescriptors and freeing memory.
|
||||||
|
@param lockbundle the lock which is to be released.
|
||||||
|
*lockbundle will be set to NULL by this call.
|
||||||
|
@return 0=success , 1=failure
|
||||||
|
*/
|
||||||
|
int ddlpa_destroy(struct ddlpa_lock **lockbundle);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/** Definitions of macros used in above functions */
|
||||||
|
|
||||||
|
#define DDLPA_OPEN_GIVEN_PATH 1
|
||||||
|
#define DDLPA_ALLOW_MISSING_SGRCD 2
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* DDLPA_H_INCLUDED */
|
@ -206,6 +206,9 @@ int burn_drive_inquire_media(struct burn_drive *d)
|
|||||||
} else {
|
} else {
|
||||||
if (d->current_profile == -1 || d->current_is_cd_profile)
|
if (d->current_profile == -1 || d->current_is_cd_profile)
|
||||||
d->read_toc(d);
|
d->read_toc(d);
|
||||||
|
|
||||||
|
/* ts A70314 */
|
||||||
|
d->status = BURN_DISC_UNSUITABLE;
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
@ -854,6 +857,35 @@ void burn_drive_set_speed(struct burn_drive *d, int r, int w)
|
|||||||
d->set_speed(d, r, w);
|
d->set_speed(d, r, w);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A70711 API function */
|
||||||
|
int burn_drive_set_buffer_waiting(struct burn_drive *d, int enable,
|
||||||
|
int min_usec, int max_usec, int timeout_sec,
|
||||||
|
int min_percent, int max_percent)
|
||||||
|
{
|
||||||
|
|
||||||
|
if (enable >= 0)
|
||||||
|
d->wait_for_buffer_free = !!enable;
|
||||||
|
if (min_usec >= 0)
|
||||||
|
d->wfb_min_usec = min_usec;
|
||||||
|
if (max_usec >= 0)
|
||||||
|
d->wfb_max_usec = max_usec;
|
||||||
|
if (timeout_sec >= 0)
|
||||||
|
d->wfb_timeout_sec = timeout_sec;
|
||||||
|
if (min_percent >= 0) {
|
||||||
|
if (min_percent < 25 || min_percent > 100)
|
||||||
|
return 0;
|
||||||
|
d->wfb_min_percent = min_percent;
|
||||||
|
}
|
||||||
|
if (max_percent >= 0) {
|
||||||
|
if (max_percent < 25 || max_percent > 100)
|
||||||
|
return 0;
|
||||||
|
d->wfb_max_percent = max_percent;
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
int burn_msf_to_sectors(int m, int s, int f)
|
int burn_msf_to_sectors(int m, int s, int f)
|
||||||
{
|
{
|
||||||
return (m * 60 + s) * 75 + f;
|
return (m * 60 + s) * 75 + f;
|
||||||
@ -1019,7 +1051,6 @@ int burn_drive_is_enumerable_adr(char *adr)
|
|||||||
#define BURN_DRIVE_MAX_LINK_DEPTH 20
|
#define BURN_DRIVE_MAX_LINK_DEPTH 20
|
||||||
|
|
||||||
/* ts A60922 ticket 33 */
|
/* ts A60922 ticket 33 */
|
||||||
/* Try to find an enumerated address with the given stat.st_rdev number */
|
|
||||||
int burn_drive_resolve_link(char *path, char adr[], int *recursion_count)
|
int burn_drive_resolve_link(char *path, char adr[], int *recursion_count)
|
||||||
{
|
{
|
||||||
int ret;
|
int ret;
|
||||||
@ -1455,11 +1486,13 @@ off_t burn_disc_available_space(struct burn_drive *d,
|
|||||||
d->send_write_parameters(d, o);
|
d->send_write_parameters(d, o);
|
||||||
d->get_nwa(d, -1, &lba, &nwa);
|
d->get_nwa(d, -1, &lba, &nwa);
|
||||||
ex:;
|
ex:;
|
||||||
|
if (o != NULL) {
|
||||||
if (o->start_byte > 0) {
|
if (o->start_byte > 0) {
|
||||||
if (o->start_byte > d->media_capacity_remaining)
|
if (o->start_byte > d->media_capacity_remaining)
|
||||||
return 0;
|
return 0;
|
||||||
return d->media_capacity_remaining - o->start_byte;
|
return d->media_capacity_remaining - o->start_byte;
|
||||||
}
|
}
|
||||||
|
}
|
||||||
return d->media_capacity_remaining;
|
return d->media_capacity_remaining;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1581,6 +1614,55 @@ int burn_drive_get_speedlist(struct burn_drive *d,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A70713 : API function */
|
||||||
|
int burn_drive_get_best_speed(struct burn_drive *d, int speed_goal,
|
||||||
|
struct burn_speed_descriptor **best_descr, int flag)
|
||||||
|
{
|
||||||
|
struct burn_speed_descriptor *sd;
|
||||||
|
int best_speed = 0, best_lba = 0, source= 2, speed;
|
||||||
|
|
||||||
|
if (flag & 2)
|
||||||
|
source = -1;
|
||||||
|
if (speed_goal < 0)
|
||||||
|
best_speed = 2000000000;
|
||||||
|
*best_descr = NULL;
|
||||||
|
for (sd = d->mdata->speed_descriptors; sd != NULL; sd = sd->next) {
|
||||||
|
if (flag & 1)
|
||||||
|
speed = sd->read_speed;
|
||||||
|
else
|
||||||
|
speed = sd->write_speed;
|
||||||
|
if ((source >= 0 && sd->source != source) ||
|
||||||
|
speed <= 0)
|
||||||
|
continue;
|
||||||
|
if (speed_goal < 0) {
|
||||||
|
if (speed < best_speed) {
|
||||||
|
best_speed = speed;
|
||||||
|
*best_descr = sd;
|
||||||
|
}
|
||||||
|
} else if (speed_goal == 0) {
|
||||||
|
if ((source == 2 && sd->end_lba > best_lba) ||
|
||||||
|
((source !=2 || sd->end_lba == best_lba) &&
|
||||||
|
speed > best_speed)) {
|
||||||
|
best_lba = sd->end_lba;
|
||||||
|
best_speed = speed;
|
||||||
|
*best_descr = sd;
|
||||||
|
}
|
||||||
|
} else if (speed <= speed_goal) {
|
||||||
|
if (speed > best_speed) {
|
||||||
|
best_speed = speed;
|
||||||
|
*best_descr = sd;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (d->current_is_cd_profile && *best_descr == NULL && ! (flag & 2))
|
||||||
|
/* Mode page 2Ah is deprecated in MMC-5 although all known
|
||||||
|
burners still support it with CD media. */
|
||||||
|
return burn_drive_get_best_speed(d, speed_goal, best_descr,
|
||||||
|
flag | 2);
|
||||||
|
return (*best_descr != NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ts A61226 : API function */
|
/* ts A61226 : API function */
|
||||||
int burn_drive_free_speedlist(struct burn_speed_descriptor **speed_list)
|
int burn_drive_free_speedlist(struct burn_speed_descriptor **speed_list)
|
||||||
{
|
{
|
||||||
@ -1615,6 +1697,7 @@ int burn_disc_get_multi_caps(struct burn_drive *d, enum burn_write_types wt,
|
|||||||
o->selected_write_mode = wt;
|
o->selected_write_mode = wt;
|
||||||
o->current_profile = d->current_profile;
|
o->current_profile = d->current_profile;
|
||||||
o->current_is_cd_profile = d->current_is_cd_profile;
|
o->current_is_cd_profile = d->current_is_cd_profile;
|
||||||
|
o->might_simulate = 0;
|
||||||
|
|
||||||
if (s != BURN_DISC_BLANK && s != BURN_DISC_APPENDABLE) {
|
if (s != BURN_DISC_BLANK && s != BURN_DISC_APPENDABLE) {
|
||||||
return 0;
|
return 0;
|
||||||
@ -1644,6 +1727,9 @@ int burn_disc_get_multi_caps(struct burn_drive *d, enum burn_write_types wt,
|
|||||||
}
|
}
|
||||||
if (wt == BURN_WRITE_RAW)
|
if (wt == BURN_WRITE_RAW)
|
||||||
o->multi_session = o->multi_track = 0;
|
o->multi_session = o->multi_track = 0;
|
||||||
|
else if(wt == BURN_WRITE_NONE || wt == BURN_WRITE_SAO ||
|
||||||
|
wt == BURN_WRITE_TAO)
|
||||||
|
o->might_simulate = !!d->mdata->simulate;
|
||||||
} else if (d->current_profile == 0x11 || d->current_profile == 0x14 ||
|
} else if (d->current_profile == 0x11 || d->current_profile == 0x14 ||
|
||||||
d->current_profile == 0x15) {
|
d->current_profile == 0x15) {
|
||||||
/* DVD-R , sequential DVD-RW , DVD-R/DL Sequential */
|
/* DVD-R , sequential DVD-RW , DVD-R/DL Sequential */
|
||||||
@ -1662,6 +1748,9 @@ int burn_disc_get_multi_caps(struct burn_drive *d, enum burn_write_types wt,
|
|||||||
}
|
}
|
||||||
if (wt == BURN_WRITE_SAO)
|
if (wt == BURN_WRITE_SAO)
|
||||||
o->multi_session = o->multi_track = 0;
|
o->multi_session = o->multi_track = 0;
|
||||||
|
if (wt == BURN_WRITE_NONE || wt == BURN_WRITE_SAO ||
|
||||||
|
wt == BURN_WRITE_TAO)
|
||||||
|
o->might_simulate = 1;
|
||||||
} else if (d->current_profile == 0x12 || d->current_profile == 0x13 ||
|
} else if (d->current_profile == 0x12 || d->current_profile == 0x13 ||
|
||||||
d->current_profile == 0x1a) {
|
d->current_profile == 0x1a) {
|
||||||
/* DVD-RAM, overwriteable DVD-RW, DVD+RW */
|
/* DVD-RAM, overwriteable DVD-RW, DVD+RW */
|
||||||
|
@ -26,9 +26,22 @@ struct libdax_msgs *libdax_messenger= NULL;
|
|||||||
|
|
||||||
int burn_running = 0;
|
int burn_running = 0;
|
||||||
|
|
||||||
/* ts A60813 : wether to use O_EXCL and/or O_NONBLOCK in libburn/sg.c */
|
/* ts A60813 : Linux: wether to use O_EXCL on open() of device files */
|
||||||
int burn_sg_open_o_excl = 1;
|
int burn_sg_open_o_excl = 1;
|
||||||
|
|
||||||
|
/* ts A70403 : Linux: wether to use fcntl(,F_SETLK,)
|
||||||
|
after open() of device files */
|
||||||
|
int burn_sg_fcntl_f_setlk = 1;
|
||||||
|
|
||||||
|
/* ts A70314 : Linux: what device family to use :
|
||||||
|
0= default family
|
||||||
|
1= sr
|
||||||
|
2= scd
|
||||||
|
(3= st)
|
||||||
|
4= sg
|
||||||
|
*/
|
||||||
|
int burn_sg_use_family = 0;
|
||||||
|
|
||||||
/* O_NONBLOCK was hardcoded in enumerate_ata() which i hardly use.
|
/* O_NONBLOCK was hardcoded in enumerate_ata() which i hardly use.
|
||||||
For enumerate_sg() it seems ok.
|
For enumerate_sg() it seems ok.
|
||||||
So it should stay default mode until enumerate_ata() without O_NONBLOCK
|
So it should stay default mode until enumerate_ata() without O_NONBLOCK
|
||||||
@ -119,10 +132,11 @@ void burn_preset_device_open(int exclusive, int blocking, int abort_on_busy)
|
|||||||
/* a ssert(burn_running); */
|
/* a ssert(burn_running); */
|
||||||
if (!burn_running)
|
if (!burn_running)
|
||||||
return;
|
return;
|
||||||
|
burn_sg_open_o_excl = exclusive & 3;
|
||||||
burn_sg_open_o_excl= exclusive;
|
burn_sg_fcntl_f_setlk = !!(exclusive & 32);
|
||||||
burn_sg_open_o_nonblock= !blocking;
|
burn_sg_use_family = (exclusive >> 2) & 7;
|
||||||
burn_sg_open_abort_busy= !!abort_on_busy;
|
burn_sg_open_o_nonblock = !blocking;
|
||||||
|
burn_sg_open_abort_busy = !!abort_on_busy;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -455,8 +455,9 @@ struct burn_progress {
|
|||||||
/* ts A61119 */
|
/* ts A61119 */
|
||||||
/** The number of bytes sent to the drive buffer */
|
/** The number of bytes sent to the drive buffer */
|
||||||
off_t buffered_bytes;
|
off_t buffered_bytes;
|
||||||
/** The minimum number of buffered bytes. (Caution: Before surely
|
/** The minimum number of bytes stored in buffer during write.
|
||||||
one buffer size of bytes was processed, this value is 0xffffffff.)
|
(Caution: Before surely one buffer size of bytes was processed,
|
||||||
|
this value is 0xffffffff.)
|
||||||
*/
|
*/
|
||||||
unsigned buffer_min_fill;
|
unsigned buffer_min_fill;
|
||||||
};
|
};
|
||||||
@ -572,13 +573,22 @@ void burn_set_verbosity(int level);
|
|||||||
after burn_initialize() and before any bus scan. But not mandatory at all.
|
after burn_initialize() and before any bus scan. But not mandatory at all.
|
||||||
Parameter value 1 enables a feature, 0 disables.
|
Parameter value 1 enables a feature, 0 disables.
|
||||||
Default is (1,0,0). Have a good reason before you change it.
|
Default is (1,0,0). Have a good reason before you change it.
|
||||||
@param exclusive 1 = Try to open only devices which are not marked as busy
|
@param exclusive Linux only:
|
||||||
|
0 = no attempt to make drive access exclusive.
|
||||||
|
1 = Try to open only devices which are not marked as busy
|
||||||
and try to mark them busy if opened sucessfully. (O_EXCL)
|
and try to mark them busy if opened sucessfully. (O_EXCL)
|
||||||
There are kernels which simply don't care about O_EXCL.
|
There are kernels which simply don't care about O_EXCL.
|
||||||
Some have it off, some have it on, some are switchable.
|
Some have it off, some have it on, some are switchable.
|
||||||
2 = in case of a SCSI device, also try to open exclusively
|
2 = in case of a SCSI device, also try to open exclusively
|
||||||
the matching /dev/sr, /dev/scd and /dev/st .
|
the matching /dev/sr, /dev/scd and /dev/st .
|
||||||
0 = no attempt to make drive access exclusive.
|
One may select a device SCSI file family by adding
|
||||||
|
0 = default family
|
||||||
|
4 = /dev/sr%d
|
||||||
|
8 = /dev/scd%d
|
||||||
|
16 = /dev/sg%d
|
||||||
|
Do not use other values !
|
||||||
|
Add 32 to demand an exclusive lock by fcntl(,F_SETLK,)
|
||||||
|
after open() has succeeded.
|
||||||
@param blocking Try to wait for drives which do not open immediately but
|
@param blocking Try to wait for drives which do not open immediately but
|
||||||
also do not return an error as well. (O_NONBLOCK)
|
also do not return an error as well. (O_NONBLOCK)
|
||||||
This might stall indefinitely with /dev/hdX hard disks.
|
This might stall indefinitely with /dev/hdX hard disks.
|
||||||
@ -765,8 +775,8 @@ int burn_drive_grab(struct burn_drive *drive, int load);
|
|||||||
|
|
||||||
|
|
||||||
/** Release a drive. This should not be done until the drive is no longer
|
/** Release a drive. This should not be done until the drive is no longer
|
||||||
busy (see burn_drive_get_status). The drive is (O_EXCL) unlocked
|
busy (see burn_drive_get_status).
|
||||||
afterwards.
|
Linux: The drive is unlocked afterwards. (O_EXCL , F_SETLK).
|
||||||
@param drive The drive to release.
|
@param drive The drive to release.
|
||||||
@param eject Nonzero to make the drive eject the disc in it.
|
@param eject Nonzero to make the drive eject the disc in it.
|
||||||
*/
|
*/
|
||||||
@ -1235,7 +1245,6 @@ enum burn_source_status burn_track_set_source(struct burn_track *t,
|
|||||||
*/
|
*/
|
||||||
int burn_track_set_default_size(struct burn_track *t, off_t size);
|
int burn_track_set_default_size(struct burn_track *t, off_t size);
|
||||||
|
|
||||||
|
|
||||||
/** Free a burn_source (decrease its refcount and maybe free it)
|
/** Free a burn_source (decrease its refcount and maybe free it)
|
||||||
@param s Source to free
|
@param s Source to free
|
||||||
*/
|
*/
|
||||||
@ -1256,6 +1265,16 @@ struct burn_source *burn_file_source_new(const char *path,
|
|||||||
struct burn_source *burn_fd_source_new(int datafd, int subfd, off_t size);
|
struct burn_source *burn_fd_source_new(int datafd, int subfd, off_t size);
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A70328 */
|
||||||
|
/** Sets a fixed track size after the data source object has already been
|
||||||
|
created.
|
||||||
|
@param t The track to poperate on
|
||||||
|
@param size the number of bytes to use as track size
|
||||||
|
@return <=0 indicates failure , >0 success
|
||||||
|
*/
|
||||||
|
int burn_track_set_size(struct burn_track *t, off_t size);
|
||||||
|
|
||||||
|
|
||||||
/** Tells how long a track will be on disc
|
/** Tells how long a track will be on disc
|
||||||
>>> NOTE: Not reliable with tracks of undefined length
|
>>> NOTE: Not reliable with tracks of undefined length
|
||||||
*/
|
*/
|
||||||
@ -1270,12 +1289,51 @@ int burn_track_get_counters(struct burn_track *t,
|
|||||||
|
|
||||||
|
|
||||||
/** Sets drive read and write speed
|
/** Sets drive read and write speed
|
||||||
|
Note: "k" is 1000, not 1024. 1xCD = 176.4 k/s, 1xDVD = 1385 k/s.
|
||||||
|
Fractional speeds should be rounded up. Like 4xCD = 706.
|
||||||
@param d The drive to set speed for
|
@param d The drive to set speed for
|
||||||
@param read Read speed in k/s (0 is max)
|
@param read Read speed in k/s (0 is max, -1 is min).
|
||||||
@param write Write speed in k/s (0 is max)
|
@param write Write speed in k/s (0 is max, -1 is min).
|
||||||
*/
|
*/
|
||||||
void burn_drive_set_speed(struct burn_drive *d, int read, int write);
|
void burn_drive_set_speed(struct burn_drive *d, int read, int write);
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A70711 */
|
||||||
|
/** Controls the behavior with writing when the drive buffer is suspected to
|
||||||
|
be full. To check and wait for enough free buffer space before writing
|
||||||
|
will move the task of waiting from the operating system's device driver
|
||||||
|
to libburn. While writing is going on and waiting is enabled, any write
|
||||||
|
operation will be checked wether it will fill the drive buffer up to
|
||||||
|
more than max_percent. If so, then waiting will happen until the buffer
|
||||||
|
fill is predicted with at most min_percent.
|
||||||
|
Thus: if min_percent < max_percent then transfer rate will oscillate.
|
||||||
|
This may allow the driver to operate on other devices, e.g. a disk from
|
||||||
|
which to read the input for writing. On the other hand, this checking might
|
||||||
|
reduce maximum throughput to the drive or even get misled by faulty buffer
|
||||||
|
fill replies from the drive.
|
||||||
|
If a setting parameter is < 0, then this setting will stay unchanged
|
||||||
|
by the call.
|
||||||
|
Known burner or media specific pitfalls:
|
||||||
|
To have max_percent larger than the burner's best reported buffer fill has
|
||||||
|
the same effect as min_percent==max_percent. Some burners do not report
|
||||||
|
their full buffer with all media types. Some are not suitable because
|
||||||
|
they report their buffer fill with delay.
|
||||||
|
@param d The drive to control
|
||||||
|
@param enable 0= disable , 1= enable waiting , (-1 = do not change setting)
|
||||||
|
@param min_usec Shortest possible sleeping period (given in micro seconds)
|
||||||
|
@param max_usec Longest possible sleeping period (given in micro seconds)
|
||||||
|
@param timeout_sec If a single write has to wait longer than this number
|
||||||
|
of seconds, then waiting gets disabled and mindless
|
||||||
|
writing starts. A value of 0 disables this timeout.
|
||||||
|
@param min_percent Minimum of desired buffer oscillation: 25 to 100
|
||||||
|
@param max_percent Maximum of desired buffer oscillation: 25 to 100
|
||||||
|
@return 1=success , 0=failure
|
||||||
|
*/
|
||||||
|
int burn_drive_set_buffer_waiting(struct burn_drive *d, int enable,
|
||||||
|
int min_usec, int max_usec, int timeout_sec,
|
||||||
|
int min_percent, int max_percent);
|
||||||
|
|
||||||
|
|
||||||
/* these are for my debugging, they will disappear */
|
/* these are for my debugging, they will disappear */
|
||||||
void burn_structure_print_disc(struct burn_disc *d);
|
void burn_structure_print_disc(struct burn_disc *d);
|
||||||
void burn_structure_print_session(struct burn_session *s);
|
void burn_structure_print_session(struct burn_session *s);
|
||||||
@ -1393,6 +1451,7 @@ void burn_write_opts_set_fillup(struct burn_write_opts *opts,
|
|||||||
/* ts A70303 */
|
/* ts A70303 */
|
||||||
/** Eventually makes libburn ignore the failure of some conformance checks:
|
/** Eventually makes libburn ignore the failure of some conformance checks:
|
||||||
- the check wether CD write+block type is supported by the drive
|
- the check wether CD write+block type is supported by the drive
|
||||||
|
- the check wether the media profile supports simulated burning
|
||||||
@param opts The write opts to change
|
@param opts The write opts to change
|
||||||
@param use_force 1=ignore above checks, 0=refuse work on failed check
|
@param use_force 1=ignore above checks, 0=refuse work on failed check
|
||||||
*/
|
*/
|
||||||
@ -1495,6 +1554,26 @@ int burn_drive_get_read_speed(struct burn_drive *d);
|
|||||||
int burn_drive_get_speedlist(struct burn_drive *d,
|
int burn_drive_get_speedlist(struct burn_drive *d,
|
||||||
struct burn_speed_descriptor **speed_list);
|
struct burn_speed_descriptor **speed_list);
|
||||||
|
|
||||||
|
/* ts A70713 */
|
||||||
|
/** Look up the fastest speed descriptor which is not faster than the given
|
||||||
|
speed_goal. If it is 0, then the fastest one is chosen among the
|
||||||
|
descriptors with the highest end_lba. If it is -1 then the slowest speed
|
||||||
|
descriptor is chosen regardless of end_lba. Parameter flag decides wether
|
||||||
|
the speed goal means write speed or read speed.
|
||||||
|
@param d Drive to query
|
||||||
|
@param speed_goal Upper limit for speed,
|
||||||
|
0=search for maximum speed , -1 search for minimum speed
|
||||||
|
@param best_descr Result of the search, NULL if no match
|
||||||
|
@param flag Bitfield for control purposes
|
||||||
|
bit0= look for best read speed rather than write speed
|
||||||
|
bit1= look for any source type (else look for source==2 first
|
||||||
|
and for any other source type only with CD media)
|
||||||
|
@return >0 indicates a valid best_descr, 0 = no valid best_descr
|
||||||
|
*/
|
||||||
|
int burn_drive_get_best_speed(struct burn_drive *d, int speed_goal,
|
||||||
|
struct burn_speed_descriptor **best_descr, int flag);
|
||||||
|
|
||||||
|
|
||||||
/* ts A61226 */
|
/* ts A61226 */
|
||||||
/** Dispose a speed descriptor list copy which was obtained by
|
/** Dispose a speed descriptor list copy which was obtained by
|
||||||
burn_drive_get_speedlist().
|
burn_drive_get_speedlist().
|
||||||
@ -1581,6 +1660,10 @@ struct burn_multi_caps {
|
|||||||
|
|
||||||
/** Wether the current profile indicates CD media. 1=yes, 0=no */
|
/** Wether the current profile indicates CD media. 1=yes, 0=no */
|
||||||
int current_is_cd_profile;
|
int current_is_cd_profile;
|
||||||
|
|
||||||
|
/* ts A70528, added to version 0.3.7 */
|
||||||
|
/** Wether the current profile is able to perform simulated write */
|
||||||
|
int might_simulate;
|
||||||
};
|
};
|
||||||
|
|
||||||
/** Allocates a struct burn_multi_caps (see above) and fills it with values
|
/** Allocates a struct burn_multi_caps (see above) and fills it with values
|
||||||
|
@ -300,9 +300,10 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
|
|||||||
0x00020002 (SORRY,HIGH) = Encountered error when closing drive
|
0x00020002 (SORRY,HIGH) = Encountered error when closing drive
|
||||||
0x00020003 (SORRY,HIGH) = Could not grab drive
|
0x00020003 (SORRY,HIGH) = Could not grab drive
|
||||||
0x00020004 (NOTE,HIGH) = Opened O_EXCL scsi sibling
|
0x00020004 (NOTE,HIGH) = Opened O_EXCL scsi sibling
|
||||||
0x00020005 (FATAL,HIGH) = Failed to open device
|
0x00020005 (SORRY,HIGH) = Failed to open device
|
||||||
0x00020006 (FATAL,HIGH) = Too many scsi siblings
|
0x00020006 (FATAL,HIGH) = Too many scsi siblings
|
||||||
0x00020007 (NOTE,HIGH) = Closed O_EXCL scsi siblings
|
0x00020007 (NOTE,HIGH) = Closed O_EXCL scsi siblings
|
||||||
|
0x00020008 (SORRY,HIGH) = Device busy. Failed to fcntl-lock
|
||||||
|
|
||||||
General library operations:
|
General library operations:
|
||||||
|
|
||||||
@ -365,6 +366,12 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
|
|||||||
0x00020138 (FATAL,HIGH) = Cannot reserve track
|
0x00020138 (FATAL,HIGH) = Cannot reserve track
|
||||||
0x00020139 (SORRY,HIGH) = Write job parameters are unsuitable
|
0x00020139 (SORRY,HIGH) = Write job parameters are unsuitable
|
||||||
0x0002013a (FATAL,HIGH) = No suitable media detected
|
0x0002013a (FATAL,HIGH) = No suitable media detected
|
||||||
|
0x0002013b (DEBUG,HIGH) = SCSI command indicates host or driver error
|
||||||
|
0x0002013c (SORRY,HIGH) = Malformed capabilities page 2Ah received
|
||||||
|
0x0002013d (DEBUG,LOW) = Waiting for free buffer space takes long time
|
||||||
|
0x0002013e (SORRY,HIGH) = Timeout with waiting for free buffer. Now disabled
|
||||||
|
0x0002013f (DEBUG,LOW) = Reporting total time spent with waiting for buffer
|
||||||
|
|
||||||
|
|
||||||
libdax_audioxtr:
|
libdax_audioxtr:
|
||||||
0x00020200 (SORRY,HIGH) = Cannot open audio source file
|
0x00020200 (SORRY,HIGH) = Cannot open audio source file
|
||||||
|
748
libburn/mmc.c
748
libburn/mmc.c
File diff suppressed because it is too large
Load Diff
@ -124,11 +124,19 @@ void burn_write_opts_set_format(struct burn_write_opts *opts, int format)
|
|||||||
|
|
||||||
int burn_write_opts_set_simulate(struct burn_write_opts *opts, int sim)
|
int burn_write_opts_set_simulate(struct burn_write_opts *opts, int sim)
|
||||||
{
|
{
|
||||||
|
/* <<< ts A70529 :
|
||||||
|
One cannot predict the ability to simulate from page 05h
|
||||||
|
information alone. This check is now done later in
|
||||||
|
function burn_write_opts_auto_write_type().
|
||||||
|
|
||||||
if (opts->drive->mdata->simulate) {
|
if (opts->drive->mdata->simulate) {
|
||||||
opts->simulate = sim;
|
opts->simulate = sim;
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
*/
|
||||||
|
opts->simulate = !!sim;
|
||||||
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
int burn_write_opts_set_underrun_proof(struct burn_write_opts *opts,
|
int burn_write_opts_set_underrun_proof(struct burn_write_opts *opts,
|
||||||
@ -265,6 +273,8 @@ no_caps:;
|
|||||||
} else if (caps->might_do_sao >= 3 && !(flag & 1))
|
} else if (caps->might_do_sao >= 3 && !(flag & 1))
|
||||||
goto try_tao;
|
goto try_tao;
|
||||||
do_sao:;
|
do_sao:;
|
||||||
|
if (caps->might_simulate == 0 && opts->simulate && !opts->force_is_set)
|
||||||
|
goto no_simulate;
|
||||||
if (!(flag & 1))
|
if (!(flag & 1))
|
||||||
burn_write_opts_set_write_type(
|
burn_write_opts_set_write_type(
|
||||||
opts, BURN_WRITE_SAO, BURN_BLOCK_SAO);
|
opts, BURN_WRITE_SAO, BURN_BLOCK_SAO);
|
||||||
@ -296,6 +306,8 @@ try_tao:;
|
|||||||
if (strcmp(reason_pt, "TAO: ") != 0)
|
if (strcmp(reason_pt, "TAO: ") != 0)
|
||||||
goto no_tao;
|
goto no_tao;
|
||||||
/* ( TAO data/audio block size will be handled automatically ) */
|
/* ( TAO data/audio block size will be handled automatically ) */
|
||||||
|
if (caps->might_simulate == 0 && opts->simulate && !opts->force_is_set)
|
||||||
|
goto no_simulate;
|
||||||
if (!(flag & 1))
|
if (!(flag & 1))
|
||||||
burn_write_opts_set_write_type(
|
burn_write_opts_set_write_type(
|
||||||
opts, BURN_WRITE_TAO, BURN_BLOCK_MODE1);
|
opts, BURN_WRITE_TAO, BURN_BLOCK_MODE1);
|
||||||
@ -323,13 +335,21 @@ try_raw:;
|
|||||||
strcat(reasons, "drive dislikes block type, ");
|
strcat(reasons, "drive dislikes block type, ");
|
||||||
if (strcmp(reason_pt, "RAW: ") != 0)
|
if (strcmp(reason_pt, "RAW: ") != 0)
|
||||||
goto no_write_mode;
|
goto no_write_mode;
|
||||||
|
if (!opts->force_is_set)
|
||||||
|
goto no_simulate;
|
||||||
|
|
||||||
/* For now: no setting of raw write modes */
|
/* For now: no setting of raw write modes */
|
||||||
|
|
||||||
{wt = BURN_WRITE_RAW; goto ex;}
|
{wt = BURN_WRITE_RAW; goto ex;}
|
||||||
|
|
||||||
no_write_mode:;
|
no_write_mode:;
|
||||||
wt = BURN_WRITE_NONE;
|
{wt = BURN_WRITE_NONE; goto ex;}
|
||||||
|
|
||||||
|
no_simulate:;
|
||||||
|
strcat(reasons,
|
||||||
|
"simulation of write job not supported by drive and media, ");
|
||||||
|
{wt = BURN_WRITE_NONE; goto ex;}
|
||||||
|
|
||||||
ex:;
|
ex:;
|
||||||
burn_disc_free_multi_caps(&caps);
|
burn_disc_free_multi_caps(&caps);
|
||||||
if (wt == BURN_WRITE_NONE && !(flag & 3)) {
|
if (wt == BURN_WRITE_NONE && !(flag & 3)) {
|
||||||
|
@ -42,7 +42,10 @@ SIGKILL, SIGCHLD, SIGSTOP, SIGURG, SIGWINCH
|
|||||||
|
|
||||||
/* The maximum size for a (SCSI) i/o transaction */
|
/* The maximum size for a (SCSI) i/o transaction */
|
||||||
/* Important : MUST be at least 32768 ! */
|
/* Important : MUST be at least 32768 ! */
|
||||||
|
/* ts A70523 : >32k seems not good with kernel 2.4 USB drivers and audio
|
||||||
#define BURN_OS_TRANSPORT_BUFFER_SIZE 65536
|
#define BURN_OS_TRANSPORT_BUFFER_SIZE 65536
|
||||||
|
*/
|
||||||
|
#define BURN_OS_TRANSPORT_BUFFER_SIZE 32768
|
||||||
|
|
||||||
|
|
||||||
/* To hold the index number of the most recently delivered address from
|
/* To hold the index number of the most recently delivered address from
|
||||||
@ -52,6 +55,10 @@ SIGKILL, SIGCHLD, SIGSTOP, SIGURG, SIGWINCH
|
|||||||
typedef int burn_drive_enumerator_t;
|
typedef int burn_drive_enumerator_t;
|
||||||
|
|
||||||
|
|
||||||
|
/* Parameters for sibling list. See sibling_fds, sibling_fnames */
|
||||||
|
#define BURN_OS_SG_MAX_SIBLINGS 5
|
||||||
|
#define BURN_OS_SG_MAX_NAMELEN 16
|
||||||
|
|
||||||
/* The list of operating system dependent elements in struct burn_drive.
|
/* The list of operating system dependent elements in struct burn_drive.
|
||||||
Usually they are initialized in sg-*.c:enumerate_common().
|
Usually they are initialized in sg-*.c:enumerate_common().
|
||||||
*/
|
*/
|
||||||
@ -60,5 +67,7 @@ int fd; \
|
|||||||
\
|
\
|
||||||
/* ts A60926 : trying to lock against growisofs /dev/srN, /dev/scdN */ \
|
/* ts A60926 : trying to lock against growisofs /dev/srN, /dev/scdN */ \
|
||||||
int sibling_count; \
|
int sibling_count; \
|
||||||
int sibling_fds[LIBBURN_SG_MAX_SIBLINGS];
|
int sibling_fds[BURN_OS_SG_MAX_SIBLINGS]; \
|
||||||
|
/* ts A70409 : DDLP */ \
|
||||||
|
char sibling_fnames[BURN_OS_SG_MAX_SIBLINGS][BURN_OS_SG_MAX_NAMELEN];
|
||||||
|
|
||||||
|
@ -3,37 +3,45 @@
|
|||||||
/* scsi block commands */
|
/* scsi block commands */
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
#include "transport.h"
|
#include "transport.h"
|
||||||
#include "sbc.h"
|
#include "sbc.h"
|
||||||
|
#include "spc.h"
|
||||||
#include "options.h"
|
#include "options.h"
|
||||||
|
|
||||||
/* spc command set */
|
/* spc command set */
|
||||||
static char SBC_LOAD[] = { 0x1b, 0, 0, 0, 3, 0 };
|
static unsigned char SBC_LOAD[] = { 0x1b, 0, 0, 0, 3, 0 };
|
||||||
static char SBC_UNLOAD[] = { 0x1b, 0, 0, 0, 2, 0 };
|
static unsigned char SBC_UNLOAD[] = { 0x1b, 0, 0, 0, 2, 0 };
|
||||||
static char SBC_START_UNIT[] = { 0x1b, 0, 0, 0, 1, 0 };
|
static unsigned char SBC_START_UNIT[] = { 0x1b, 0, 0, 0, 1, 0 };
|
||||||
|
|
||||||
void sbc_load(struct burn_drive *d)
|
void sbc_load(struct burn_drive *d)
|
||||||
{
|
{
|
||||||
struct command c;
|
struct command c;
|
||||||
|
|
||||||
|
scsi_init_command(&c, SBC_LOAD, sizeof(SBC_LOAD));
|
||||||
|
/*
|
||||||
memcpy(c.opcode, SBC_LOAD, sizeof(SBC_LOAD));
|
memcpy(c.opcode, SBC_LOAD, sizeof(SBC_LOAD));
|
||||||
c.retry = 1;
|
|
||||||
c.oplen = sizeof(SBC_LOAD);
|
c.oplen = sizeof(SBC_LOAD);
|
||||||
c.dir = NO_TRANSFER;
|
|
||||||
c.page = NULL;
|
c.page = NULL;
|
||||||
|
*/
|
||||||
|
c.retry = 1;
|
||||||
|
c.dir = NO_TRANSFER;
|
||||||
d->issue_command(d, &c);
|
d->issue_command(d, &c);
|
||||||
|
spc_wait_unit_attention(d, 60);
|
||||||
}
|
}
|
||||||
|
|
||||||
void sbc_eject(struct burn_drive *d)
|
void sbc_eject(struct burn_drive *d)
|
||||||
{
|
{
|
||||||
struct command c;
|
struct command c;
|
||||||
|
|
||||||
c.page = NULL;
|
scsi_init_command(&c, SBC_UNLOAD, sizeof(SBC_UNLOAD));
|
||||||
|
/*
|
||||||
memcpy(c.opcode, SBC_UNLOAD, sizeof(SBC_UNLOAD));
|
memcpy(c.opcode, SBC_UNLOAD, sizeof(SBC_UNLOAD));
|
||||||
c.oplen = 1;
|
|
||||||
c.oplen = sizeof(SBC_UNLOAD);
|
c.oplen = sizeof(SBC_UNLOAD);
|
||||||
c.page = NULL;
|
c.page = NULL;
|
||||||
|
*/
|
||||||
|
c.page = NULL;
|
||||||
c.dir = NO_TRANSFER;
|
c.dir = NO_TRANSFER;
|
||||||
d->issue_command(d, &c);
|
d->issue_command(d, &c);
|
||||||
}
|
}
|
||||||
@ -43,11 +51,14 @@ int sbc_start_unit(struct burn_drive *d)
|
|||||||
{
|
{
|
||||||
struct command c;
|
struct command c;
|
||||||
|
|
||||||
|
scsi_init_command(&c, SBC_START_UNIT, sizeof(SBC_START_UNIT));
|
||||||
|
/*
|
||||||
memcpy(c.opcode, SBC_START_UNIT, sizeof(SBC_START_UNIT));
|
memcpy(c.opcode, SBC_START_UNIT, sizeof(SBC_START_UNIT));
|
||||||
c.retry = 1;
|
|
||||||
c.oplen = sizeof(SBC_START_UNIT);
|
c.oplen = sizeof(SBC_START_UNIT);
|
||||||
c.dir = NO_TRANSFER;
|
|
||||||
c.page = NULL;
|
c.page = NULL;
|
||||||
|
*/
|
||||||
|
c.retry = 1;
|
||||||
|
c.dir = NO_TRANSFER;
|
||||||
d->issue_command(d, &c);
|
d->issue_command(d, &c);
|
||||||
return (c.error==0);
|
return (c.error==0);
|
||||||
}
|
}
|
||||||
|
@ -218,7 +218,8 @@ static unsigned char *get_sector(struct burn_write_opts *opts,
|
|||||||
seclen += burn_subcode_length(outmode);
|
seclen += burn_subcode_length(outmode);
|
||||||
|
|
||||||
/* ts A61219 : opts->obs is eventually a 32k trigger for DVD */
|
/* ts A61219 : opts->obs is eventually a 32k trigger for DVD */
|
||||||
if (out->bytes + (seclen) > BUFFER_SIZE || out->bytes == opts->obs) {
|
if (out->bytes + seclen > BUFFER_SIZE ||
|
||||||
|
(opts->obs > 0 && out->bytes + seclen > opts->obs)) {
|
||||||
int err;
|
int err;
|
||||||
err = d->write(d, d->nwa, out);
|
err = d->write(d, d->nwa, out);
|
||||||
if (err == BE_CANCELLED)
|
if (err == BE_CANCELLED)
|
||||||
|
@ -71,14 +71,26 @@ Hint: You should also look into sg-freebsd-port.c, which is a younger and
|
|||||||
#include <sys/poll.h>
|
#include <sys/poll.h>
|
||||||
#include <linux/hdreg.h>
|
#include <linux/hdreg.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <scsi/sg.h>
|
#include <sys/utsname.h>
|
||||||
#include <scsi/scsi.h>
|
#include <scsi/scsi.h>
|
||||||
|
|
||||||
/* ts A61211 : to recognize CD devices on /dev/sr* */
|
#include <scsi/sg.h>
|
||||||
|
/* Values within sg_io_hdr_t indicating success after ioctl(SG_IO) : */
|
||||||
|
/* .host_status : from http://tldp.org/HOWTO/SCSI-Generic-HOWTO/x291.html */
|
||||||
|
#define Libburn_sg_host_oK 0
|
||||||
|
/* .driver_status : from http://tldp.org/HOWTO/SCSI-Generic-HOWTO/x322.html */
|
||||||
|
#define Libburn_sg_driver_oK 0
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A61211 : to eventually recognize CD devices on /dev/sr* */
|
||||||
#include <linux/cdrom.h>
|
#include <linux/cdrom.h>
|
||||||
|
|
||||||
|
|
||||||
/* ts A61211 : preparing for exploration of recent Linux ATA adventures */
|
/** Indication of the Linux kernel this software is running on */
|
||||||
|
/* -1 = not evaluated , 0 = unrecognizable , 1 = 2.4 , 2 = 2.6 */
|
||||||
|
static int sg_kernel_age = -1;
|
||||||
|
|
||||||
|
|
||||||
/** PORTING : Device file families for bus scanning and drive access.
|
/** PORTING : Device file families for bus scanning and drive access.
|
||||||
Both device families must support the following ioctls:
|
Both device families must support the following ioctls:
|
||||||
SG_IO,
|
SG_IO,
|
||||||
@ -104,22 +116,22 @@ static int linux_sg_enumerate_debug = 0;
|
|||||||
in the range of 0 to 31 . The resulting addresses must provide SCSI
|
in the range of 0 to 31 . The resulting addresses must provide SCSI
|
||||||
address parameters Host, Channel, Id, Lun and also Bus.
|
address parameters Host, Channel, Id, Lun and also Bus.
|
||||||
E.g.: "/dev/sg%d"
|
E.g.: "/dev/sg%d"
|
||||||
|
sr%d is supposed to map only CD-ROM style devices. Additionally a test
|
||||||
|
with ioctl(CDROM_DRIVE_STATUS) is made to assert that it is such a drive,
|
||||||
|
|
||||||
|
This initial setting may be overridden in sg_select_device_family() by
|
||||||
|
settings made via burn_preset_device_open().
|
||||||
*/
|
*/
|
||||||
/* NEW INFO: If hard disks at /dev/sr allow ioctl(CDROM_DRIVE_STATUS), they
|
|
||||||
are in danger.
|
|
||||||
If you want it less dangerous:
|
|
||||||
#undef CDROM_DRIVE_STATUS
|
|
||||||
but then you might need linux_sg_accept_any_type = 1 which
|
|
||||||
is _more dangerous_.
|
|
||||||
*/
|
|
||||||
/* !!! DO NOT SET TO sr%d UNLESS YOU PROTECTED ALL INDISPENSIBLE DEVICES
|
|
||||||
by chmod -rw . A test wether non-CD devices are properly excluded would
|
|
||||||
be well needed though. Heroic disks, scanners, etc. wanted !!! */
|
|
||||||
static char linux_sg_device_family[80] = {"/dev/sg%d"};
|
static char linux_sg_device_family[80] = {"/dev/sg%d"};
|
||||||
|
|
||||||
|
/* Set this to 1 if you want the default linux_sg_device_family chosen
|
||||||
|
depending on kernel release: sg for <2.6 , sr for >=2.6
|
||||||
|
*/
|
||||||
|
static int linux_sg_auto_family = 1;
|
||||||
|
|
||||||
|
|
||||||
/* Set this to 1 in order to accept any TYPE_* (see scsi/scsi.h) */
|
/* Set this to 1 in order to accept any TYPE_* (see scsi/scsi.h) */
|
||||||
/* NEW INFO: Try with 0 first. There is hope via CDROM_DRIVE_STATUS. */
|
/* But try with 0 first. There is hope via CDROM_DRIVE_STATUS. */
|
||||||
/* !!! DO NOT SET TO 1 UNLESS YOU PROTECTED ALL INDISPENSIBLE DEVICES
|
/* !!! DO NOT SET TO 1 UNLESS YOU PROTECTED ALL INDISPENSIBLE DEVICES
|
||||||
chmod -rw !!! */
|
chmod -rw !!! */
|
||||||
static int linux_sg_accept_any_type = 0;
|
static int linux_sg_accept_any_type = 0;
|
||||||
@ -168,12 +180,15 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
|
|||||||
int channel_no, int target_no, int lun_no);
|
int channel_no, int target_no, int lun_no);
|
||||||
|
|
||||||
|
|
||||||
/* >>> ts A61115 : this needs mending. A Linux aspect shows up in cdrskin. */
|
|
||||||
/* ts A60813 : storage objects are in libburn/init.c
|
/* ts A60813 : storage objects are in libburn/init.c
|
||||||
wether to use O_EXCL
|
wether to use O_EXCL with open(2) of devices
|
||||||
|
wether to use fcntl(,F_SETLK,) after open(2) of devices
|
||||||
|
what device family to use : 0=default, 1=sr, 2=scd, (3=st), 4=sg
|
||||||
wether to use O_NOBLOCK with open(2) on devices
|
wether to use O_NOBLOCK with open(2) on devices
|
||||||
wether to take O_EXCL rejection as fatal error */
|
wether to take O_EXCL rejection as fatal error */
|
||||||
extern int burn_sg_open_o_excl;
|
extern int burn_sg_open_o_excl;
|
||||||
|
extern int burn_sg_fcntl_f_setlk;
|
||||||
|
extern int burn_sg_use_family;
|
||||||
extern int burn_sg_open_o_nonblock;
|
extern int burn_sg_open_o_nonblock;
|
||||||
extern int burn_sg_open_abort_busy;
|
extern int burn_sg_open_abort_busy;
|
||||||
|
|
||||||
@ -188,6 +203,53 @@ int mmc_function_spy(char * text);
|
|||||||
/* (Public functions are listed below) */
|
/* (Public functions are listed below) */
|
||||||
/* ------------------------------------------------------------------------ */
|
/* ------------------------------------------------------------------------ */
|
||||||
|
|
||||||
|
/* ts A70413 */
|
||||||
|
/* This finds out wether the software is running on kernel >= 2.6
|
||||||
|
*/
|
||||||
|
static void sg_evaluate_kernel(void)
|
||||||
|
{
|
||||||
|
struct utsname buf;
|
||||||
|
if (sg_kernel_age >= 0)
|
||||||
|
return;
|
||||||
|
|
||||||
|
sg_kernel_age = 0;
|
||||||
|
if (uname(&buf) == -1)
|
||||||
|
return;
|
||||||
|
sg_kernel_age = 1;
|
||||||
|
if (strcmp(buf.release, "2.6") >= 0)
|
||||||
|
sg_kernel_age = 2;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A70314 */
|
||||||
|
/* This installs the device file family if one was chosen explicitely
|
||||||
|
by burn_preset_device_open()
|
||||||
|
*/
|
||||||
|
static void sg_select_device_family(void)
|
||||||
|
{
|
||||||
|
|
||||||
|
/* >>> ??? do we need a mutex here ? */
|
||||||
|
/* >>> (It might be concurrent but is supposed to have always
|
||||||
|
the same effect. Any race condition should be harmless.) */
|
||||||
|
|
||||||
|
if (burn_sg_use_family == 1)
|
||||||
|
strcpy(linux_sg_device_family, "/dev/sr%d");
|
||||||
|
else if (burn_sg_use_family == 2)
|
||||||
|
strcpy(linux_sg_device_family, "/dev/scd%d");
|
||||||
|
else if (burn_sg_use_family == 3)
|
||||||
|
strcpy(linux_sg_device_family, "/dev/st%d");
|
||||||
|
else if (burn_sg_use_family == 4)
|
||||||
|
strcpy(linux_sg_device_family, "/dev/sg%d");
|
||||||
|
else if (linux_sg_auto_family) {
|
||||||
|
sg_evaluate_kernel();
|
||||||
|
if (sg_kernel_age >= 2)
|
||||||
|
strcpy(linux_sg_device_family, "/dev/sr%d");
|
||||||
|
else
|
||||||
|
strcpy(linux_sg_device_family, "/dev/sg%d");
|
||||||
|
linux_sg_auto_family = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
static int sgio_test(int fd)
|
static int sgio_test(int fd)
|
||||||
{
|
{
|
||||||
@ -229,12 +291,86 @@ static int sg_handle_busy_device(char *fname, int os_errno)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A60925 : ticket 74 */
|
||||||
|
static int sg_close_drive_fd(char *fname, int driveno, int *fd, int sorry)
|
||||||
|
{
|
||||||
|
int ret, os_errno, sevno= LIBDAX_MSGS_SEV_DEBUG;
|
||||||
|
char msg[4096+100];
|
||||||
|
|
||||||
|
if(*fd < 0)
|
||||||
|
return(0);
|
||||||
|
ret = close(*fd);
|
||||||
|
*fd = -1337;
|
||||||
|
if(ret != -1) {
|
||||||
|
/* ts A70409 : DDLP-B */
|
||||||
|
/* >>> release single lock on fname */
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
os_errno= errno;
|
||||||
|
|
||||||
|
sprintf(msg, "Encountered error when closing drive '%s'", fname);
|
||||||
|
if (sorry)
|
||||||
|
sevno = LIBDAX_MSGS_SEV_SORRY;
|
||||||
|
libdax_msgs_submit(libdax_messenger, driveno, 0x00020002,
|
||||||
|
sevno, LIBDAX_MSGS_PRIO_HIGH, msg, os_errno, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A70401 :
|
||||||
|
fcntl() has the unappealing property to work only after open().
|
||||||
|
So libburn will by default use open(O_EXCL) first and afterwards
|
||||||
|
as second assertion will use fcntl(F_SETLK). One lock more should not harm.
|
||||||
|
*/
|
||||||
|
static int sg_fcntl_lock(int *fd, char *fd_name, int l_type, int verbous)
|
||||||
|
{
|
||||||
|
struct flock lockthing;
|
||||||
|
char msg[81];
|
||||||
|
int ret;
|
||||||
|
|
||||||
|
if (!burn_sg_fcntl_f_setlk)
|
||||||
|
return 1;
|
||||||
|
|
||||||
|
memset(&lockthing, 0, sizeof(lockthing));
|
||||||
|
lockthing.l_type = l_type;
|
||||||
|
lockthing.l_whence = SEEK_SET;
|
||||||
|
lockthing.l_start = 0;
|
||||||
|
lockthing.l_len = 0;
|
||||||
|
/*
|
||||||
|
fprintf(stderr,"LIBBURN_EXPERIMENTAL: fcntl(%d, F_SETLK, %s)\n",
|
||||||
|
*fd, l_type == F_WRLCK ? "F_WRLCK" : "F_RDLCK");
|
||||||
|
*/
|
||||||
|
|
||||||
|
ret = fcntl(*fd, F_SETLK, &lockthing);
|
||||||
|
if (ret == -1) {
|
||||||
|
if (verbous) {
|
||||||
|
sprintf(msg, "Device busy. Failed to fcntl-lock '%s'",
|
||||||
|
fd_name);
|
||||||
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020008,
|
||||||
|
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
msg, errno, 0);
|
||||||
|
}
|
||||||
|
close(*fd);
|
||||||
|
*fd = -1;
|
||||||
|
|
||||||
|
/* ts A70409 : DDLP-B */
|
||||||
|
/* >>> release single lock on fd_name */
|
||||||
|
|
||||||
|
return(0);
|
||||||
|
}
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ts A60926 */
|
/* ts A60926 */
|
||||||
static int sg_open_drive_fd(char *fname, int scan_mode)
|
static int sg_open_drive_fd(char *fname, int scan_mode)
|
||||||
{
|
{
|
||||||
int open_mode = O_RDWR, fd;
|
int open_mode = O_RDWR, fd;
|
||||||
char msg[81];
|
char msg[81];
|
||||||
|
|
||||||
|
/* ts A70409 : DDLP-B */
|
||||||
|
/* >>> obtain single lock on fname */
|
||||||
|
|
||||||
/* ts A60813 - A60927
|
/* ts A60813 - A60927
|
||||||
O_EXCL with devices is a non-POSIX feature
|
O_EXCL with devices is a non-POSIX feature
|
||||||
of Linux kernels. Possibly introduced 2002.
|
of Linux kernels. Possibly introduced 2002.
|
||||||
@ -244,17 +380,22 @@ static int sg_open_drive_fd(char *fname, int scan_mode)
|
|||||||
/* ts A60813
|
/* ts A60813
|
||||||
O_NONBLOCK was already hardcoded in ata_ but not in sg_.
|
O_NONBLOCK was already hardcoded in ata_ but not in sg_.
|
||||||
There must be some reason for this. So O_NONBLOCK is
|
There must be some reason for this. So O_NONBLOCK is
|
||||||
default mode for both now. Disable on own risk. */
|
default mode for both now. Disable on own risk.
|
||||||
|
ts A70411
|
||||||
|
Switched to O_NDELAY for LKML statement 2007/4/11/141 by Alan Cox:
|
||||||
|
"open() has side effects. The CD layer allows you to open
|
||||||
|
with O_NDELAY if you want to avoid them."
|
||||||
|
*/
|
||||||
if(burn_sg_open_o_nonblock)
|
if(burn_sg_open_o_nonblock)
|
||||||
open_mode |= O_NONBLOCK;
|
open_mode |= O_NDELAY;
|
||||||
|
|
||||||
/* <<< debugging
|
/* <<< debugging
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"\nlibburn: experimental: o_excl= %d , o_nonblock= %d, abort_on_busy= %d\n",
|
"\nlibburn: experimental: o_excl= %d , o_nonblock= %d, abort_on_busy= %d\n",
|
||||||
burn_sg_open_o_excl,burn_sg_open_o_nonblock,burn_sg_open_abort_busy);
|
burn_sg_open_o_excl,burn_sg_open_o_nonblock,burn_sg_open_abort_busy);
|
||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"libburn: experimental: O_EXCL= %d , O_NONBLOCK= %d\n",
|
"libburn: experimental: O_EXCL= %d , O_NDELAY= %d\n",
|
||||||
!!(open_mode&O_EXCL),!!(open_mode&O_NONBLOCK));
|
!!(open_mode&O_EXCL),!!(open_mode&O_NDELAY));
|
||||||
*/
|
*/
|
||||||
|
|
||||||
fd = open(fname, open_mode);
|
fd = open(fname, open_mode);
|
||||||
@ -273,50 +414,25 @@ static int sg_open_drive_fd(char *fname, int scan_mode)
|
|||||||
return -1;
|
return -1;
|
||||||
sprintf(msg, "Failed to open device '%s'",fname);
|
sprintf(msg, "Failed to open device '%s'",fname);
|
||||||
libdax_msgs_submit(libdax_messenger, -1, 0x00020005,
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020005,
|
||||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
msg, errno, 0);
|
msg, errno, 0);
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
sg_fcntl_lock(&fd, fname, F_WRLCK, 1);
|
||||||
return fd;
|
return fd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ts A60925 : ticket 74 */
|
|
||||||
static int sg_close_drive_fd(char *fname, int driveno, int *fd, int sorry)
|
|
||||||
{
|
|
||||||
int ret, os_errno, sevno= LIBDAX_MSGS_SEV_DEBUG;
|
|
||||||
char msg[4096+100];
|
|
||||||
|
|
||||||
if(*fd < 0)
|
|
||||||
return(0);
|
|
||||||
ret = close(*fd);
|
|
||||||
*fd = -1337;
|
|
||||||
if(ret != -1)
|
|
||||||
return 1;
|
|
||||||
os_errno= errno;
|
|
||||||
|
|
||||||
if (fname != NULL)
|
|
||||||
sprintf(msg, "Encountered error when closing drive '%s'",
|
|
||||||
fname);
|
|
||||||
else
|
|
||||||
sprintf(msg, "Encountered error when closing drive");
|
|
||||||
|
|
||||||
if (sorry)
|
|
||||||
sevno = LIBDAX_MSGS_SEV_SORRY;
|
|
||||||
libdax_msgs_submit(libdax_messenger, driveno, 0x00020002,
|
|
||||||
sevno, LIBDAX_MSGS_PRIO_HIGH, msg, os_errno, 0);
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A60926 */
|
/* ts A60926 */
|
||||||
static int sg_release_siblings(int sibling_fds[], int *sibling_count)
|
static int sg_release_siblings(int sibling_fds[],
|
||||||
|
char sibling_fnames[][BURN_OS_SG_MAX_NAMELEN],
|
||||||
|
int *sibling_count)
|
||||||
{
|
{
|
||||||
int i;
|
int i;
|
||||||
char msg[81];
|
char msg[81];
|
||||||
|
|
||||||
for(i= 0; i < *sibling_count; i++)
|
for(i= 0; i < *sibling_count; i++)
|
||||||
sg_close_drive_fd(NULL, -1, &(sibling_fds[i]), 0);
|
sg_close_drive_fd(sibling_fnames[i], -1, &(sibling_fds[i]), 0);
|
||||||
if(*sibling_count > 0) {
|
if(*sibling_count > 0) {
|
||||||
sprintf(msg, "Closed %d O_EXCL scsi siblings", *sibling_count);
|
sprintf(msg, "Closed %d O_EXCL scsi siblings", *sibling_count);
|
||||||
libdax_msgs_submit(libdax_messenger, -1, 0x00020007,
|
libdax_msgs_submit(libdax_messenger, -1, 0x00020007,
|
||||||
@ -334,7 +450,8 @@ static int sg_close_drive(struct burn_drive *d)
|
|||||||
|
|
||||||
if (!burn_drive_is_open(d))
|
if (!burn_drive_is_open(d))
|
||||||
return 0;
|
return 0;
|
||||||
sg_release_siblings(d->sibling_fds, &(d->sibling_count));
|
sg_release_siblings(d->sibling_fds, d->sibling_fnames,
|
||||||
|
&(d->sibling_count));
|
||||||
ret = sg_close_drive_fd(d->devname, d->global_index, &(d->fd), 0);
|
ret = sg_close_drive_fd(d->devname, d->global_index, &(d->fd), 0);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
@ -342,29 +459,45 @@ static int sg_close_drive(struct burn_drive *d)
|
|||||||
|
|
||||||
/* ts A60926 */
|
/* ts A60926 */
|
||||||
static int sg_open_scsi_siblings(char *path, int driveno,
|
static int sg_open_scsi_siblings(char *path, int driveno,
|
||||||
int sibling_fds[], int *sibling_count,
|
int sibling_fds[],
|
||||||
|
char sibling_fnames[][BURN_OS_SG_MAX_NAMELEN],
|
||||||
|
int *sibling_count,
|
||||||
int host_no, int channel_no, int id_no, int lun_no)
|
int host_no, int channel_no, int id_no, int lun_no)
|
||||||
{
|
{
|
||||||
int tld, i, ret, fd, i_bus_no = -1;
|
int tld, i, ret, fd, i_bus_no = -1;
|
||||||
int i_host_no = -1, i_channel_no = -1, i_target_no = -1, i_lun_no = -1;
|
int i_host_no = -1, i_channel_no = -1, i_target_no = -1, i_lun_no = -1;
|
||||||
char msg[161], fname[81];
|
char msg[161], fname[81];
|
||||||
|
struct stat stbuf;
|
||||||
|
dev_t last_rdev = 0, path_rdev;
|
||||||
|
|
||||||
static char tldev[][81]= {"/dev/sr%d", "/dev/scd%d", "/dev/st%d",
|
static char tldev[][81]= {"/dev/sr%d", "/dev/scd%d", "/dev/sg%d", ""};
|
||||||
"/dev/sg%d", ""};
|
/* ts A70609: removed "/dev/st%d" */
|
||||||
|
|
||||||
|
if(stat(path, &stbuf) == -1)
|
||||||
|
return 0;
|
||||||
|
path_rdev = stbuf.st_rdev;
|
||||||
|
|
||||||
|
sg_select_device_family();
|
||||||
if (linux_sg_device_family[0] == 0)
|
if (linux_sg_device_family[0] == 0)
|
||||||
return 1;
|
return 1;
|
||||||
|
|
||||||
if(host_no < 0 || id_no < 0 || channel_no < 0 || lun_no < 0)
|
if(host_no < 0 || id_no < 0 || channel_no < 0 || lun_no < 0)
|
||||||
return(2);
|
return(2);
|
||||||
if(*sibling_count > 0)
|
if(*sibling_count > 0)
|
||||||
sg_release_siblings(sibling_fds, sibling_count);
|
sg_release_siblings(sibling_fds, sibling_fnames,
|
||||||
|
sibling_count);
|
||||||
|
|
||||||
for (tld = 0; tldev[tld][0] != 0; tld++) {
|
for (tld = 0; tldev[tld][0] != 0; tld++) {
|
||||||
if (strcmp(tldev[tld], linux_sg_device_family)==0)
|
if (strcmp(tldev[tld], linux_sg_device_family)==0)
|
||||||
continue;
|
continue;
|
||||||
for (i = 0; i < 32; i++) {
|
for (i = 0; i < 32; i++) {
|
||||||
sprintf(fname, tldev[tld], i);
|
sprintf(fname, tldev[tld], i);
|
||||||
|
if(stat(fname, &stbuf) == -1)
|
||||||
|
continue;
|
||||||
|
if (path_rdev == stbuf.st_rdev)
|
||||||
|
continue;
|
||||||
|
if (*sibling_count > 0 && last_rdev == stbuf.st_rdev)
|
||||||
|
continue;
|
||||||
ret = sg_obtain_scsi_adr(fname, &i_bus_no, &i_host_no,
|
ret = sg_obtain_scsi_adr(fname, &i_bus_no, &i_host_no,
|
||||||
&i_channel_no, &i_target_no, &i_lun_no);
|
&i_channel_no, &i_target_no, &i_lun_no);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
@ -378,7 +511,7 @@ static int sg_open_scsi_siblings(char *path, int driveno,
|
|||||||
if (fd < 0)
|
if (fd < 0)
|
||||||
goto failed;
|
goto failed;
|
||||||
|
|
||||||
if (*sibling_count>=LIBBURN_SG_MAX_SIBLINGS) {
|
if (*sibling_count>=BURN_OS_SG_MAX_SIBLINGS) {
|
||||||
sprintf(msg, "Too many scsi siblings of '%s'",
|
sprintf(msg, "Too many scsi siblings of '%s'",
|
||||||
path);
|
path);
|
||||||
libdax_msgs_submit(libdax_messenger,
|
libdax_msgs_submit(libdax_messenger,
|
||||||
@ -394,12 +527,14 @@ static int sg_open_scsi_siblings(char *path, int driveno,
|
|||||||
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
|
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
msg, 0, 0);
|
msg, 0, 0);
|
||||||
sibling_fds[*sibling_count] = fd;
|
sibling_fds[*sibling_count] = fd;
|
||||||
|
strcpy(sibling_fnames[*sibling_count], fname);
|
||||||
(*sibling_count)++;
|
(*sibling_count)++;
|
||||||
|
last_rdev= stbuf.st_rdev;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return 1;
|
return 1;
|
||||||
failed:;
|
failed:;
|
||||||
sg_release_siblings(sibling_fds, sibling_count);
|
sg_release_siblings(sibling_fds, sibling_fnames, sibling_count);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -477,10 +612,13 @@ static void ata_enumerate(void)
|
|||||||
static void sg_enumerate(void)
|
static void sg_enumerate(void)
|
||||||
{
|
{
|
||||||
struct sg_scsi_id sid;
|
struct sg_scsi_id sid;
|
||||||
int i, fd, sibling_fds[LIBBURN_SG_MAX_SIBLINGS], sibling_count= 0, ret;
|
int i, fd, sibling_fds[BURN_OS_SG_MAX_SIBLINGS], sibling_count= 0, ret;
|
||||||
int sid_ret = 0;
|
int sid_ret = 0;
|
||||||
int bus_no= -1, host_no= -1, channel_no= -1, target_no= -1, lun_no= -1;
|
int bus_no= -1, host_no= -1, channel_no= -1, target_no= -1, lun_no= -1;
|
||||||
char fname[10];
|
char fname[10];
|
||||||
|
char sibling_fnames[BURN_OS_SG_MAX_SIBLINGS][BURN_OS_SG_MAX_NAMELEN];
|
||||||
|
|
||||||
|
sg_select_device_family();
|
||||||
|
|
||||||
if (linux_sg_enumerate_debug)
|
if (linux_sg_enumerate_debug)
|
||||||
fprintf(stderr, "libburn_debug: linux_sg_device_family = %s\n",
|
fprintf(stderr, "libburn_debug: linux_sg_device_family = %s\n",
|
||||||
@ -520,6 +658,16 @@ static void sg_enumerate(void)
|
|||||||
"ioctl(SG_GET_SCSI_ID) failed, errno=%d '%s' , ",
|
"ioctl(SG_GET_SCSI_ID) failed, errno=%d '%s' , ",
|
||||||
errno, strerror(errno));
|
errno, strerror(errno));
|
||||||
|
|
||||||
|
if (sgio_test(fd) == -1) {
|
||||||
|
if (linux_sg_enumerate_debug)
|
||||||
|
fprintf(stderr,
|
||||||
|
"FATAL: sgio_test() failed: errno=%d '%s'",
|
||||||
|
errno, strerror(errno));
|
||||||
|
|
||||||
|
sg_close_drive_fd(fname, -1, &fd, 0);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef CDROM_DRIVE_STATUS
|
#ifdef CDROM_DRIVE_STATUS
|
||||||
/* ts A61211 : not widening old acceptance range */
|
/* ts A61211 : not widening old acceptance range */
|
||||||
if (strcmp(linux_sg_device_family,"/dev/sg%d") != 0) {
|
if (strcmp(linux_sg_device_family,"/dev/sg%d") != 0) {
|
||||||
@ -581,7 +729,8 @@ static void sg_enumerate(void)
|
|||||||
/* ts A60927 : trying to do locking with growisofs */
|
/* ts A60927 : trying to do locking with growisofs */
|
||||||
if(burn_sg_open_o_excl>1) {
|
if(burn_sg_open_o_excl>1) {
|
||||||
ret = sg_open_scsi_siblings(
|
ret = sg_open_scsi_siblings(
|
||||||
fname, -1, sibling_fds, &sibling_count,
|
fname, -1, sibling_fds, sibling_fnames,
|
||||||
|
&sibling_count,
|
||||||
sid.host_no, sid.channel,
|
sid.host_no, sid.channel,
|
||||||
sid.scsi_id, sid.lun);
|
sid.scsi_id, sid.lun);
|
||||||
if (ret<=0) {
|
if (ret<=0) {
|
||||||
@ -591,7 +740,8 @@ static void sg_enumerate(void)
|
|||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
/* the final occupation will be done in sg_grab() */
|
/* the final occupation will be done in sg_grab() */
|
||||||
sg_release_siblings(sibling_fds, &sibling_count);
|
sg_release_siblings(sibling_fds, sibling_fnames,
|
||||||
|
&sibling_count);
|
||||||
}
|
}
|
||||||
#ifdef SCSI_IOCTL_GET_BUS_NUMBER
|
#ifdef SCSI_IOCTL_GET_BUS_NUMBER
|
||||||
if(bus_no == -1)
|
if(bus_no == -1)
|
||||||
@ -645,7 +795,7 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
|
|||||||
/* Adapter specific handles and data */
|
/* Adapter specific handles and data */
|
||||||
out.fd = -1337;
|
out.fd = -1337;
|
||||||
out.sibling_count = 0;
|
out.sibling_count = 0;
|
||||||
for(i= 0; i<LIBBURN_SG_MAX_SIBLINGS; i++)
|
for(i= 0; i<BURN_OS_SG_MAX_SIBLINGS; i++)
|
||||||
out.sibling_fds[i] = -1337;
|
out.sibling_fds[i] = -1337;
|
||||||
|
|
||||||
/* PORTING: ---------------- end of non portable part ------------ */
|
/* PORTING: ---------------- end of non portable part ------------ */
|
||||||
@ -698,6 +848,7 @@ int sg_give_next_adr(burn_drive_enumerator_t *idx,
|
|||||||
if (initialize == -1)
|
if (initialize == -1)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
sg_select_device_family();
|
||||||
if (linux_sg_device_family[0] == 0)
|
if (linux_sg_device_family[0] == 0)
|
||||||
sg_limit = 0;
|
sg_limit = 0;
|
||||||
if (linux_ata_device_family[0] == 0)
|
if (linux_ata_device_family[0] == 0)
|
||||||
@ -793,9 +944,12 @@ int sg_grab(struct burn_drive *d)
|
|||||||
open_mode |= O_EXCL;
|
open_mode |= O_EXCL;
|
||||||
|
|
||||||
/* ts A60813
|
/* ts A60813
|
||||||
O_NONBLOCK was hardcoded here. So it should stay default mode. */
|
O_NONBLOCK was hardcoded here. So it should stay default mode.
|
||||||
|
ts A70411
|
||||||
|
Switched to O_NDELAY for LKML statement 2007/4/11/141
|
||||||
|
*/
|
||||||
if(burn_sg_open_o_nonblock)
|
if(burn_sg_open_o_nonblock)
|
||||||
open_mode |= O_NONBLOCK;
|
open_mode |= O_NDELAY;
|
||||||
|
|
||||||
/* ts A60813 - A60822
|
/* ts A60813 - A60822
|
||||||
After enumeration the drive fd is probably still open.
|
After enumeration the drive fd is probably still open.
|
||||||
@ -808,12 +962,15 @@ int sg_grab(struct burn_drive *d)
|
|||||||
<<< debug: for tracing calls which might use open drive fds */
|
<<< debug: for tracing calls which might use open drive fds */
|
||||||
mmc_function_spy("sg_grab ----------- opening");
|
mmc_function_spy("sg_grab ----------- opening");
|
||||||
|
|
||||||
|
/* ts A70409 : DDLP-B */
|
||||||
|
/* >>> obtain single lock on d->devname */
|
||||||
|
|
||||||
/* ts A60926 */
|
/* ts A60926 */
|
||||||
if(burn_sg_open_o_excl>1) {
|
if(burn_sg_open_o_excl>1) {
|
||||||
fd = -1;
|
fd = -1;
|
||||||
ret = sg_open_scsi_siblings(d->devname,
|
ret = sg_open_scsi_siblings(d->devname,
|
||||||
d->global_index,d->sibling_fds,
|
d->global_index,d->sibling_fds,
|
||||||
&(d->sibling_count),
|
d->sibling_fnames,&(d->sibling_count),
|
||||||
d->host, d->channel, d->id, d->lun);
|
d->host, d->channel, d->id, d->lun);
|
||||||
if(ret <= 0)
|
if(ret <= 0)
|
||||||
goto drive_is_in_use;
|
goto drive_is_in_use;
|
||||||
@ -821,6 +978,11 @@ int sg_grab(struct burn_drive *d)
|
|||||||
|
|
||||||
fd = open(d->devname, open_mode);
|
fd = open(d->devname, open_mode);
|
||||||
os_errno = errno;
|
os_errno = errno;
|
||||||
|
if (fd >= 0) {
|
||||||
|
sg_fcntl_lock(&fd, d->devname, F_WRLCK, 1);
|
||||||
|
if (fd < 0)
|
||||||
|
goto drive_is_in_use;
|
||||||
|
}
|
||||||
} else
|
} else
|
||||||
fd= d->fd;
|
fd= d->fd;
|
||||||
|
|
||||||
@ -872,6 +1034,71 @@ int sg_release(struct burn_drive *d)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** ts A70518:
|
||||||
|
Debugging log facility. Controlled by existence of macros:
|
||||||
|
Libburn_log_sg_commandS enables logging to file
|
||||||
|
/tmp/libburn_sg_command_log
|
||||||
|
Libburn_fflush_log_sg_commandS enables fflush after each output line
|
||||||
|
Libburn_log_sg_command_stderR enables additional log to stderr
|
||||||
|
*/
|
||||||
|
/*
|
||||||
|
#define Libburn_log_sg_commandS 1
|
||||||
|
#define Libburn_fflush_log_sg_commandS 1
|
||||||
|
#define Libburn_log_sg_command_stderR 1
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifdef Libburn_log_sg_commandS
|
||||||
|
|
||||||
|
/** Logs command (before execution) */
|
||||||
|
static int sg_log_cmd(struct command *c, FILE *fp, int flag)
|
||||||
|
{
|
||||||
|
int i;
|
||||||
|
|
||||||
|
if (fp != NULL) {
|
||||||
|
for(i = 0; i < 16 && i < c->oplen; i++)
|
||||||
|
fprintf(fp,"%2.2x ", c->opcode[i]);
|
||||||
|
fprintf(fp, "\n");
|
||||||
|
#ifdef Libburn_fflush_log_sg_commandS
|
||||||
|
fflush(fp);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (fp == stderr)
|
||||||
|
return 1;
|
||||||
|
#ifdef Libburn_log_sg_command_stderR
|
||||||
|
sg_log_cmd(c, stderr, flag);
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/** logs outcome of a sg command. flag&1 causes an error message */
|
||||||
|
static int sg_log_err(struct command *c, FILE *fp,
|
||||||
|
sg_io_hdr_t *s,
|
||||||
|
int flag)
|
||||||
|
{
|
||||||
|
if(fp!=NULL) {
|
||||||
|
if(flag & 1)
|
||||||
|
fprintf(fp,
|
||||||
|
"+++ key=%X asc=%2.2Xh ascq=%2.2Xh (%6d ms)\n",
|
||||||
|
s->sbp[2], s->sbp[12], s->sbp[13],s->duration);
|
||||||
|
else
|
||||||
|
fprintf(fp,"%6d ms\n", s->duration);
|
||||||
|
#ifdef Libburn_fflush_log_sg_commandS
|
||||||
|
fflush(fp);
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
if (fp == stderr)
|
||||||
|
return 1;
|
||||||
|
#ifdef Libburn_log_sg_command_stderR
|
||||||
|
sg_log_err(c, stderr, s, flag);
|
||||||
|
#endif
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
#endif /* Libburn_log_sg_commandS */
|
||||||
|
|
||||||
|
|
||||||
/** Sends a SCSI command to the drive, receives reply and evaluates wether
|
/** Sends a SCSI command to the drive, receives reply and evaluates wether
|
||||||
the command succeeded or shall be retried or finally failed.
|
the command succeeded or shall be retried or finally failed.
|
||||||
Returned SCSI errors shall not lead to a return value indicating failure.
|
Returned SCSI errors shall not lead to a return value indicating failure.
|
||||||
@ -886,15 +1113,10 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
|
|||||||
int done = 0, no_c_page = 0;
|
int done = 0, no_c_page = 0;
|
||||||
int err;
|
int err;
|
||||||
sg_io_hdr_t s;
|
sg_io_hdr_t s;
|
||||||
/*
|
|
||||||
#define Libburn_log_sg_commandS 1
|
|
||||||
*/
|
|
||||||
|
|
||||||
#ifdef Libburn_log_sg_commandS
|
#ifdef Libburn_log_sg_commandS
|
||||||
/* ts A61030 */
|
/* ts A61030 */
|
||||||
static FILE *fp= NULL;
|
static FILE *fp= NULL;
|
||||||
static int fpcount= 0;
|
|
||||||
int i;
|
|
||||||
#endif /* Libburn_log_sg_commandS */
|
#endif /* Libburn_log_sg_commandS */
|
||||||
|
|
||||||
/* <<< ts A60821
|
/* <<< ts A60821
|
||||||
@ -910,12 +1132,7 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
|
|||||||
fp= fopen("/tmp/libburn_sg_command_log","a");
|
fp= fopen("/tmp/libburn_sg_command_log","a");
|
||||||
fprintf(fp,"\n-----------------------------------------\n");
|
fprintf(fp,"\n-----------------------------------------\n");
|
||||||
}
|
}
|
||||||
if(fp!=NULL) {
|
sg_log_cmd(c,fp,0);
|
||||||
for(i=0;i<10;i++)
|
|
||||||
fprintf(fp,"%2.2x ", c->opcode[i]);
|
|
||||||
fprintf(fp,"\n");
|
|
||||||
fpcount++;
|
|
||||||
}
|
|
||||||
#endif /* Libburn_log_sg_commandS */
|
#endif /* Libburn_log_sg_commandS */
|
||||||
|
|
||||||
|
|
||||||
@ -950,6 +1167,14 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
|
|||||||
if (c->page && !no_c_page) {
|
if (c->page && !no_c_page) {
|
||||||
s.dxferp = c->page->data;
|
s.dxferp = c->page->data;
|
||||||
if (c->dir == FROM_DRIVE) {
|
if (c->dir == FROM_DRIVE) {
|
||||||
|
|
||||||
|
/* ts A70519 : kernel 2.4 usb-storage seems to
|
||||||
|
expect exact dxfer_len for data
|
||||||
|
fetching commands.
|
||||||
|
*/
|
||||||
|
if (c->dxfer_len >= 0)
|
||||||
|
s.dxfer_len = c->dxfer_len;
|
||||||
|
else
|
||||||
s.dxfer_len = BUFFER_SIZE;
|
s.dxfer_len = BUFFER_SIZE;
|
||||||
/* touch page so we can use valgrind */
|
/* touch page so we can use valgrind */
|
||||||
memset(c->page->data, 0, BUFFER_SIZE);
|
memset(c->page->data, 0, BUFFER_SIZE);
|
||||||
@ -1013,16 +1238,27 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
|
|||||||
ex:;
|
ex:;
|
||||||
if (c->error) {
|
if (c->error) {
|
||||||
scsi_notify_error(d, c, s.sbp, s.sb_len_wr, 0);
|
scsi_notify_error(d, c, s.sbp, s.sb_len_wr, 0);
|
||||||
|
} else if (s.host_status != Libburn_sg_host_oK ||
|
||||||
|
s.driver_status != Libburn_sg_driver_oK) {
|
||||||
|
char msg[161];
|
||||||
|
|
||||||
|
sprintf(msg,
|
||||||
|
"SCSI command %2.2Xh indicates host or driver error:",
|
||||||
|
(unsigned int) c->opcode[0]);
|
||||||
|
sprintf(msg+strlen(msg),
|
||||||
|
" host_status= %xh , driver_status= %xh",
|
||||||
|
(unsigned int) s.host_status,
|
||||||
|
(unsigned int) s.driver_status);
|
||||||
|
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||||
|
0x0002013b,
|
||||||
|
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
msg, 0, 0);
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef Libburn_log_sg_commandS
|
#ifdef Libburn_log_sg_commandS
|
||||||
if(fp!=NULL) {
|
sg_log_err(c, fp, &s, c->error != 0);
|
||||||
fprintf(fp,"+++ key=%X asc=%2.2Xh ascq=%2.2Xh\n",
|
|
||||||
s.sbp[2], s.sbp[12], s.sbp[13]);
|
|
||||||
fpcount++;
|
|
||||||
}
|
|
||||||
#endif /* Libburn_log_sg_commandS */
|
#endif /* Libburn_log_sg_commandS */
|
||||||
|
|
||||||
}
|
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1034,19 +1270,33 @@ ex:;
|
|||||||
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
|
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
|
||||||
int *target_no, int *lun_no)
|
int *target_no, int *lun_no)
|
||||||
{
|
{
|
||||||
int fd, ret, l;
|
int fd, ret, l, open_mode = O_RDONLY;
|
||||||
struct my_scsi_idlun {
|
struct my_scsi_idlun {
|
||||||
int x;
|
int x;
|
||||||
int host_unique_id;
|
int host_unique_id;
|
||||||
};
|
};
|
||||||
struct my_scsi_idlun idlun;
|
struct my_scsi_idlun idlun;
|
||||||
|
|
||||||
|
|
||||||
l = strlen(linux_ata_device_family) - 2;
|
l = strlen(linux_ata_device_family) - 2;
|
||||||
if (l > 0 && strncmp(path, linux_ata_device_family, l) == 0
|
if (l > 0 && strncmp(path, linux_ata_device_family, l) == 0
|
||||||
&& path[7] >= 'a' && path[7] <= 'z' && path[8] == 0)
|
&& path[7] >= 'a' && path[7] <= 'z' && path[8] == 0)
|
||||||
return 0; /* on RIP 14 all hdx return SCSI adr 0,0,0,0 */
|
return 0; /* on RIP 14 all hdx return SCSI adr 0,0,0,0 */
|
||||||
|
|
||||||
fd = open(path, O_RDONLY | O_NONBLOCK);
|
/* ts A70409 : DDLP-B */
|
||||||
|
/* >>> obtain single lock on path */
|
||||||
|
|
||||||
|
if(burn_sg_open_o_nonblock)
|
||||||
|
open_mode |= O_NDELAY;
|
||||||
|
if(burn_sg_open_o_excl) {
|
||||||
|
/* O_EXCL | O_RDONLY does not work with /dev/sg* on
|
||||||
|
SuSE 9.0 (kernel 2.4) and SuSE 9.3 (kernel 2.6) */
|
||||||
|
/* so skip it for now */;
|
||||||
|
}
|
||||||
|
fd = open(path, open_mode);
|
||||||
|
if(fd < 0)
|
||||||
|
return 0;
|
||||||
|
sg_fcntl_lock(&fd, path, F_RDLCK, 0);
|
||||||
if(fd < 0)
|
if(fd < 0)
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
|
191
libburn/spc.c
191
libburn/spc.c
@ -29,7 +29,8 @@ extern struct libdax_msgs *libdax_messenger;
|
|||||||
|
|
||||||
|
|
||||||
/* spc command set */
|
/* spc command set */
|
||||||
static unsigned char SPC_INQUIRY[] = { 0x12, 0, 0, 0, 255, 0 };
|
/* ts A70519 : allocation length byte 3+4 was 0,255 */
|
||||||
|
static unsigned char SPC_INQUIRY[] = { 0x12, 0, 0, 0, 36, 0 };
|
||||||
|
|
||||||
/*static char SPC_TEST[]={0,0,0,0,0,0};*/
|
/*static char SPC_TEST[]={0,0,0,0,0,0};*/
|
||||||
static unsigned char SPC_PREVENT[] = { 0x1e, 0, 0, 0, 1, 0 };
|
static unsigned char SPC_PREVENT[] = { 0x1e, 0, 0, 0, 1, 0 };
|
||||||
@ -40,28 +41,84 @@ static unsigned char SPC_MODE_SELECT[] =
|
|||||||
static unsigned char SPC_REQUEST_SENSE[] = { 0x03, 0, 0, 0, 18, 0 };
|
static unsigned char SPC_REQUEST_SENSE[] = { 0x03, 0, 0, 0, 18, 0 };
|
||||||
static unsigned char SPC_TEST_UNIT_READY[] = { 0x00, 0, 0, 0, 0, 0 };
|
static unsigned char SPC_TEST_UNIT_READY[] = { 0x00, 0, 0, 0, 0, 0 };
|
||||||
|
|
||||||
int spc_test_unit_ready(struct burn_drive *d)
|
|
||||||
|
/* ts A70519 : An initializer for the abstract SCSI command structure */
|
||||||
|
int scsi_init_command(struct command *c, unsigned char *opcode, int oplen)
|
||||||
|
{
|
||||||
|
if (oplen > 16)
|
||||||
|
return 0;
|
||||||
|
memcpy(c->opcode, opcode, oplen);
|
||||||
|
c->oplen = oplen;
|
||||||
|
c->dir = NO_TRANSFER;
|
||||||
|
c->dxfer_len = -1;
|
||||||
|
memset(c->sense, 0, sizeof(c->sense));
|
||||||
|
c->error = 0;
|
||||||
|
c->retry = 0;
|
||||||
|
c->page = NULL;
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
int spc_test_unit_ready_r(struct burn_drive *d, int *key, int *asc, int *ascq)
|
||||||
{
|
{
|
||||||
struct command c;
|
struct command c;
|
||||||
|
|
||||||
c.retry = 0;
|
scsi_init_command(&c, SPC_TEST_UNIT_READY,sizeof(SPC_TEST_UNIT_READY));
|
||||||
|
/*
|
||||||
c.oplen = sizeof(SPC_TEST_UNIT_READY);
|
c.oplen = sizeof(SPC_TEST_UNIT_READY);
|
||||||
memcpy(c.opcode, SPC_TEST_UNIT_READY, sizeof(SPC_TEST_UNIT_READY));
|
memcpy(c.opcode, SPC_TEST_UNIT_READY, sizeof(SPC_TEST_UNIT_READY));
|
||||||
c.page = NULL;
|
c.page = NULL;
|
||||||
|
*/
|
||||||
|
c.retry = 0;
|
||||||
c.dir = NO_TRANSFER;
|
c.dir = NO_TRANSFER;
|
||||||
d->issue_command(d, &c);
|
d->issue_command(d, &c);
|
||||||
if (c.error)
|
if (c.error) {
|
||||||
|
*key= c.sense[2];
|
||||||
|
*asc= c.sense[12];
|
||||||
|
*ascq= c.sense[13];
|
||||||
return (c.sense[2] & 0xF) == 0;
|
return (c.sense[2] & 0xF) == 0;
|
||||||
|
}
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
int spc_test_unit_ready(struct burn_drive *d)
|
||||||
|
{
|
||||||
|
int key,asc,ascq;
|
||||||
|
|
||||||
|
return spc_test_unit_ready_r(d, &key, &asc, &ascq);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A70315 */
|
||||||
|
/** Wait until the drive state becomes clear or until max_usec elapsed */
|
||||||
|
int spc_wait_unit_attention(struct burn_drive *d, int max_sec)
|
||||||
|
{
|
||||||
|
int i, ret, key, asc, ascq;
|
||||||
|
|
||||||
|
for(i=0; i < max_sec; i++) {
|
||||||
|
ret = spc_test_unit_ready_r(d, &key, &asc, &ascq);
|
||||||
|
if(ret > 0 || key!=0x2 || asc!=0x4) /* ready or error */
|
||||||
|
break;
|
||||||
|
usleep(1000000);
|
||||||
|
}
|
||||||
|
if (i < max_sec)
|
||||||
|
return (ret > 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void spc_request_sense(struct burn_drive *d, struct buffer *buf)
|
void spc_request_sense(struct burn_drive *d, struct buffer *buf)
|
||||||
{
|
{
|
||||||
struct command c;
|
struct command c;
|
||||||
|
|
||||||
|
scsi_init_command(&c, SPC_REQUEST_SENSE, sizeof(SPC_REQUEST_SENSE));
|
||||||
c.retry = 0;
|
c.retry = 0;
|
||||||
|
/*
|
||||||
c.oplen = sizeof(SPC_REQUEST_SENSE);
|
c.oplen = sizeof(SPC_REQUEST_SENSE);
|
||||||
memcpy(c.opcode, SPC_REQUEST_SENSE, sizeof(SPC_REQUEST_SENSE));
|
memcpy(c.opcode, SPC_REQUEST_SENSE, sizeof(SPC_REQUEST_SENSE));
|
||||||
|
*/
|
||||||
|
c.dxfer_len= c.opcode[4];
|
||||||
|
c.retry = 0;
|
||||||
c.page = buf;
|
c.page = buf;
|
||||||
c.page->sectors = 0;
|
c.page->sectors = 0;
|
||||||
c.page->bytes = 0;
|
c.page->bytes = 0;
|
||||||
@ -83,24 +140,29 @@ void spc_inquiry(struct burn_drive *d)
|
|||||||
struct burn_scsi_inquiry_data *id;
|
struct burn_scsi_inquiry_data *id;
|
||||||
struct command c;
|
struct command c;
|
||||||
|
|
||||||
|
scsi_init_command(&c, SPC_INQUIRY, sizeof(SPC_INQUIRY));
|
||||||
|
/*
|
||||||
memcpy(c.opcode, SPC_INQUIRY, sizeof(SPC_INQUIRY));
|
memcpy(c.opcode, SPC_INQUIRY, sizeof(SPC_INQUIRY));
|
||||||
c.retry = 1;
|
|
||||||
c.oplen = sizeof(SPC_INQUIRY);
|
c.oplen = sizeof(SPC_INQUIRY);
|
||||||
|
*/
|
||||||
|
c.dxfer_len= (c.opcode[3] << 8) | c.opcode[4];
|
||||||
|
c.retry = 1;
|
||||||
c.page = &buf;
|
c.page = &buf;
|
||||||
c.page->bytes = 0;
|
c.page->bytes = 0;
|
||||||
c.page->sectors = 0;
|
c.page->sectors = 0;
|
||||||
c.dir = FROM_DRIVE;
|
c.dir = FROM_DRIVE;
|
||||||
d->issue_command(d, &c);
|
d->issue_command(d, &c);
|
||||||
|
|
||||||
id = (struct burn_scsi_inquiry_data *)d->idata;
|
id = (struct burn_scsi_inquiry_data *)d->idata;
|
||||||
id->vendor[8] = 0;
|
memset(id->vendor, 0, 9);
|
||||||
id->product[16] = 0;
|
memset(id->product, 0, 17);
|
||||||
id->revision[4] = 0;
|
memset(id->revision, 0, 5);
|
||||||
|
if (c.error) {
|
||||||
|
id->valid = -1;
|
||||||
|
return;
|
||||||
|
}
|
||||||
memcpy(id->vendor, c.page->data + 8, 8);
|
memcpy(id->vendor, c.page->data + 8, 8);
|
||||||
memcpy(id->product, c.page->data + 16, 16);
|
memcpy(id->product, c.page->data + 16, 16);
|
||||||
memcpy(id->revision, c.page->data + 32, 4);
|
memcpy(id->revision, c.page->data + 32, 4);
|
||||||
|
|
||||||
id->valid = 1;
|
id->valid = 1;
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@ -109,10 +171,13 @@ void spc_prevent(struct burn_drive *d)
|
|||||||
{
|
{
|
||||||
struct command c;
|
struct command c;
|
||||||
|
|
||||||
|
scsi_init_command(&c, SPC_PREVENT, sizeof(SPC_PREVENT));
|
||||||
|
/*
|
||||||
memcpy(c.opcode, SPC_PREVENT, sizeof(SPC_PREVENT));
|
memcpy(c.opcode, SPC_PREVENT, sizeof(SPC_PREVENT));
|
||||||
c.retry = 1;
|
|
||||||
c.oplen = sizeof(SPC_PREVENT);
|
c.oplen = sizeof(SPC_PREVENT);
|
||||||
c.page = NULL;
|
c.page = NULL;
|
||||||
|
*/
|
||||||
|
c.retry = 1;
|
||||||
c.dir = NO_TRANSFER;
|
c.dir = NO_TRANSFER;
|
||||||
d->issue_command(d, &c);
|
d->issue_command(d, &c);
|
||||||
}
|
}
|
||||||
@ -121,19 +186,27 @@ void spc_allow(struct burn_drive *d)
|
|||||||
{
|
{
|
||||||
struct command c;
|
struct command c;
|
||||||
|
|
||||||
|
scsi_init_command(&c, SPC_ALLOW, sizeof(SPC_ALLOW));
|
||||||
|
/*
|
||||||
memcpy(c.opcode, SPC_ALLOW, sizeof(SPC_ALLOW));
|
memcpy(c.opcode, SPC_ALLOW, sizeof(SPC_ALLOW));
|
||||||
c.retry = 1;
|
|
||||||
c.oplen = sizeof(SPC_ALLOW);
|
c.oplen = sizeof(SPC_ALLOW);
|
||||||
c.page = NULL;
|
c.page = NULL;
|
||||||
|
*/
|
||||||
|
c.retry = 1;
|
||||||
c.dir = NO_TRANSFER;
|
c.dir = NO_TRANSFER;
|
||||||
d->issue_command(d, &c);
|
d->issue_command(d, &c);
|
||||||
}
|
}
|
||||||
|
|
||||||
void spc_sense_caps(struct burn_drive *d)
|
/*
|
||||||
|
ts A70518 : Do not call with *alloc_len < 8
|
||||||
|
*/
|
||||||
|
/** flag&1= do only inquire alloc_len */
|
||||||
|
static int spc_sense_caps_al(struct burn_drive *d, int *alloc_len, int flag)
|
||||||
{
|
{
|
||||||
struct buffer buf;
|
struct buffer buf;
|
||||||
struct scsi_mode_data *m;
|
struct scsi_mode_data *m;
|
||||||
int size, page_length, num_write_speeds = 0, i, speed, ret;
|
int size, page_length, num_write_speeds = 0, i, speed, ret;
|
||||||
|
int old_alloc_len, was_error = 0;
|
||||||
unsigned char *page;
|
unsigned char *page;
|
||||||
struct command c;
|
struct command c;
|
||||||
struct burn_speed_descriptor *sd;
|
struct burn_speed_descriptor *sd;
|
||||||
@ -141,15 +214,30 @@ void spc_sense_caps(struct burn_drive *d)
|
|||||||
/* ts A61225 : 1 = report about post-MMC-1 speed descriptors */
|
/* ts A61225 : 1 = report about post-MMC-1 speed descriptors */
|
||||||
static int speed_debug = 0;
|
static int speed_debug = 0;
|
||||||
|
|
||||||
|
if (*alloc_len < 8)
|
||||||
|
return 0;
|
||||||
|
|
||||||
|
memset(&buf, 0, sizeof(buf));
|
||||||
|
scsi_init_command(&c, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE));
|
||||||
|
/*
|
||||||
memcpy(c.opcode, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE));
|
memcpy(c.opcode, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE));
|
||||||
c.retry = 1;
|
|
||||||
c.oplen = sizeof(SPC_MODE_SENSE);
|
c.oplen = sizeof(SPC_MODE_SENSE);
|
||||||
|
*/
|
||||||
|
c.dxfer_len = *alloc_len;
|
||||||
|
c.opcode[7] = (c.dxfer_len >> 8) & 0xff;
|
||||||
|
c.opcode[8] = c.dxfer_len & 0xff;
|
||||||
|
c.retry = 1;
|
||||||
c.opcode[2] = 0x2A;
|
c.opcode[2] = 0x2A;
|
||||||
c.page = &buf;
|
c.page = &buf;
|
||||||
c.page->bytes = 0;
|
c.page->bytes = 0;
|
||||||
c.page->sectors = 0;
|
c.page->sectors = 0;
|
||||||
c.dir = FROM_DRIVE;
|
c.dir = FROM_DRIVE;
|
||||||
d->issue_command(d, &c);
|
d->issue_command(d, &c);
|
||||||
|
if (c.error) {
|
||||||
|
memset(&buf, 0, sizeof(buf));
|
||||||
|
d->mdata->valid = -1;
|
||||||
|
was_error = 1;
|
||||||
|
}
|
||||||
|
|
||||||
size = c.page->data[0] * 256 + c.page->data[1];
|
size = c.page->data[0] * 256 + c.page->data[1];
|
||||||
m = d->mdata;
|
m = d->mdata;
|
||||||
@ -162,6 +250,14 @@ void spc_sense_caps(struct burn_drive *d)
|
|||||||
set of speed descriptors. In MMC-5 E.11 it is declared "legacy".
|
set of speed descriptors. In MMC-5 E.11 it is declared "legacy".
|
||||||
*/
|
*/
|
||||||
page_length = page[1];
|
page_length = page[1];
|
||||||
|
old_alloc_len = *alloc_len;
|
||||||
|
*alloc_len = page_length + 8;
|
||||||
|
if (flag & 1)
|
||||||
|
return !was_error;
|
||||||
|
if (page_length + 8 > old_alloc_len)
|
||||||
|
page_length = old_alloc_len - 8;
|
||||||
|
if (page_length < 22)
|
||||||
|
return 0;
|
||||||
|
|
||||||
m->valid = 0;
|
m->valid = 0;
|
||||||
burn_mdata_free_subs(m);
|
burn_mdata_free_subs(m);
|
||||||
@ -211,6 +307,18 @@ void spc_sense_caps(struct burn_drive *d)
|
|||||||
|
|
||||||
num_write_speeds = page[30] * 256 + page[31];
|
num_write_speeds = page[30] * 256 + page[31];
|
||||||
m->max_write_speed = m->min_write_speed = m->cur_write_speed;
|
m->max_write_speed = m->min_write_speed = m->cur_write_speed;
|
||||||
|
|
||||||
|
if (32 + 4 * num_write_speeds > page_length + 2) {
|
||||||
|
char msg[161];
|
||||||
|
|
||||||
|
sprintf(msg, "Malformed capabilities page 2Ah received (len=%d, #speeds=%d)", page_length, num_write_speeds);
|
||||||
|
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||||
|
0x0002013c,
|
||||||
|
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||||
|
msg, 0, 0);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < num_write_speeds; i++) {
|
for (i = 0; i < num_write_speeds; i++) {
|
||||||
speed = page[32 + 4*i + 2] * 256 + page[32 + 4*i + 3];
|
speed = page[32 + 4*i + 2] * 256 + page[32 + 4*i + 3];
|
||||||
|
|
||||||
@ -252,6 +360,24 @@ try_mmc_get_performance:;
|
|||||||
fprintf(stderr,
|
fprintf(stderr,
|
||||||
"LIBBURN_DEBUG: ACh min_write_speed = %d , max_write_speed = %d\n",
|
"LIBBURN_DEBUG: ACh min_write_speed = %d , max_write_speed = %d\n",
|
||||||
m->min_write_speed, m->max_write_speed);
|
m->min_write_speed, m->max_write_speed);
|
||||||
|
return !was_error;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void spc_sense_caps(struct burn_drive *d)
|
||||||
|
{
|
||||||
|
int alloc_len, start_len = 22, ret;
|
||||||
|
|
||||||
|
/* first command execution to learn Allocation Length */
|
||||||
|
alloc_len = start_len;
|
||||||
|
ret = spc_sense_caps_al(d, &alloc_len, 1);
|
||||||
|
/*
|
||||||
|
fprintf(stderr,"LIBBURN_DEBUG: 5Ah alloc_len = %d , ret = %d\n",
|
||||||
|
alloc_len, ret);
|
||||||
|
*/
|
||||||
|
if (alloc_len >= start_len && ret > 0)
|
||||||
|
/* second execution with announced length */
|
||||||
|
spc_sense_caps_al(d, &alloc_len, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -259,13 +385,19 @@ void spc_sense_error_params(struct burn_drive *d)
|
|||||||
{
|
{
|
||||||
struct buffer buf;
|
struct buffer buf;
|
||||||
struct scsi_mode_data *m;
|
struct scsi_mode_data *m;
|
||||||
int size;
|
int size, alloc_len = 12 ;
|
||||||
unsigned char *page;
|
unsigned char *page;
|
||||||
struct command c;
|
struct command c;
|
||||||
|
|
||||||
|
scsi_init_command(&c, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE));
|
||||||
|
/*
|
||||||
memcpy(c.opcode, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE));
|
memcpy(c.opcode, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE));
|
||||||
c.retry = 1;
|
|
||||||
c.oplen = sizeof(SPC_MODE_SENSE);
|
c.oplen = sizeof(SPC_MODE_SENSE);
|
||||||
|
*/
|
||||||
|
c.dxfer_len = alloc_len;
|
||||||
|
c.opcode[7] = (c.dxfer_len >> 8) & 0xff;
|
||||||
|
c.opcode[8] = c.dxfer_len & 0xff;
|
||||||
|
c.retry = 1;
|
||||||
c.opcode[2] = 0x01;
|
c.opcode[2] = 0x01;
|
||||||
c.page = &buf;
|
c.page = &buf;
|
||||||
c.page->bytes = 0;
|
c.page->bytes = 0;
|
||||||
@ -287,9 +419,12 @@ void spc_select_error_params(struct burn_drive *d,
|
|||||||
struct buffer buf;
|
struct buffer buf;
|
||||||
struct command c;
|
struct command c;
|
||||||
|
|
||||||
|
scsi_init_command(&c, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT));
|
||||||
|
/*
|
||||||
memcpy(c.opcode, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT));
|
memcpy(c.opcode, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT));
|
||||||
c.retry = 1;
|
|
||||||
c.oplen = sizeof(SPC_MODE_SELECT);
|
c.oplen = sizeof(SPC_MODE_SELECT);
|
||||||
|
*/
|
||||||
|
c.retry = 1;
|
||||||
c.opcode[8] = 8 + 2 + d->mdata->retry_page_length;
|
c.opcode[8] = 8 + 2 + d->mdata->retry_page_length;
|
||||||
c.page = &buf;
|
c.page = &buf;
|
||||||
c.page->bytes = 0;
|
c.page->bytes = 0;
|
||||||
@ -318,7 +453,7 @@ void spc_sense_write_params(struct burn_drive *d)
|
|||||||
{
|
{
|
||||||
struct buffer buf;
|
struct buffer buf;
|
||||||
struct scsi_mode_data *m;
|
struct scsi_mode_data *m;
|
||||||
int size, dummy;
|
int size, dummy, alloc_len = 10;
|
||||||
unsigned char *page;
|
unsigned char *page;
|
||||||
struct command c;
|
struct command c;
|
||||||
|
|
||||||
@ -326,9 +461,15 @@ void spc_sense_write_params(struct burn_drive *d)
|
|||||||
/* a ssert(d->mdata->cdr_write || d->mdata->cdrw_write ||
|
/* a ssert(d->mdata->cdr_write || d->mdata->cdrw_write ||
|
||||||
d->mdata->dvdr_write || d->mdata->dvdram_write); */
|
d->mdata->dvdr_write || d->mdata->dvdram_write); */
|
||||||
|
|
||||||
|
scsi_init_command(&c, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE));
|
||||||
|
/*
|
||||||
memcpy(c.opcode, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE));
|
memcpy(c.opcode, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE));
|
||||||
c.retry = 1;
|
|
||||||
c.oplen = sizeof(SPC_MODE_SENSE);
|
c.oplen = sizeof(SPC_MODE_SENSE);
|
||||||
|
*/
|
||||||
|
c.dxfer_len = alloc_len;
|
||||||
|
c.opcode[7] = (c.dxfer_len >> 8) & 0xff;
|
||||||
|
c.opcode[8] = c.dxfer_len & 0xff;
|
||||||
|
c.retry = 1;
|
||||||
c.opcode[2] = 0x05;
|
c.opcode[2] = 0x05;
|
||||||
c.page = &buf;
|
c.page = &buf;
|
||||||
c.page->bytes = 0;
|
c.page->bytes = 0;
|
||||||
@ -383,9 +524,12 @@ void spc_select_write_params(struct burn_drive *d,
|
|||||||
o->block_type,spc_block_type(o->block_type));
|
o->block_type,spc_block_type(o->block_type));
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
scsi_init_command(&c, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT));
|
||||||
|
/*
|
||||||
memcpy(c.opcode, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT));
|
memcpy(c.opcode, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT));
|
||||||
c.retry = 1;
|
|
||||||
c.oplen = sizeof(SPC_MODE_SELECT);
|
c.oplen = sizeof(SPC_MODE_SELECT);
|
||||||
|
*/
|
||||||
|
c.retry = 1;
|
||||||
c.opcode[8] = 8 + 2 + d->mdata->write_page_length;
|
c.opcode[8] = 8 + 2 + d->mdata->write_page_length;
|
||||||
c.page = &buf;
|
c.page = &buf;
|
||||||
c.page->bytes = 0;
|
c.page->bytes = 0;
|
||||||
@ -443,9 +587,12 @@ void spc_probe_write_modes(struct burn_drive *d)
|
|||||||
try_block_type = useable_block_type;
|
try_block_type = useable_block_type;
|
||||||
last_try= 1;
|
last_try= 1;
|
||||||
}
|
}
|
||||||
|
scsi_init_command(&c, SPC_MODE_SELECT,sizeof(SPC_MODE_SELECT));
|
||||||
|
/*
|
||||||
memcpy(c.opcode, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT));
|
memcpy(c.opcode, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT));
|
||||||
c.retry = 1;
|
|
||||||
c.oplen = sizeof(SPC_MODE_SELECT);
|
c.oplen = sizeof(SPC_MODE_SELECT);
|
||||||
|
*/
|
||||||
|
c.retry = 1;
|
||||||
c.opcode[8] = 8 + 2 + 0x32;
|
c.opcode[8] = 8 + 2 + 0x32;
|
||||||
c.page = &buf;
|
c.page = &buf;
|
||||||
|
|
||||||
|
@ -20,8 +20,16 @@ void spc_probe_write_modes(struct burn_drive *);
|
|||||||
void spc_request_sense(struct burn_drive *d, struct buffer *buf);
|
void spc_request_sense(struct burn_drive *d, struct buffer *buf);
|
||||||
int spc_block_type(enum burn_block_types b);
|
int spc_block_type(enum burn_block_types b);
|
||||||
int spc_get_erase_progress(struct burn_drive *d);
|
int spc_get_erase_progress(struct burn_drive *d);
|
||||||
|
|
||||||
|
/* ts A70315 : test_unit_ready with result parameters */
|
||||||
|
int spc_test_unit_ready_r(struct burn_drive *d, int *key, int *asc, int *ascq);
|
||||||
|
|
||||||
int spc_test_unit_ready(struct burn_drive *d);
|
int spc_test_unit_ready(struct burn_drive *d);
|
||||||
|
|
||||||
|
/* ts A70315 */
|
||||||
|
/** Wait until the drive state becomes clear in or until max_sec elapsed */
|
||||||
|
int spc_wait_unit_attention(struct burn_drive *d, int max_sec);
|
||||||
|
|
||||||
/* ts A61021 : the spc specific part of sg.c:enumerate_common()
|
/* ts A61021 : the spc specific part of sg.c:enumerate_common()
|
||||||
*/
|
*/
|
||||||
int spc_setup_drive(struct burn_drive *d);
|
int spc_setup_drive(struct burn_drive *d);
|
||||||
@ -47,4 +55,7 @@ enum response scsi_error_msg(struct burn_drive *d, unsigned char *sense,
|
|||||||
int scsi_notify_error(struct burn_drive *, struct command *c,
|
int scsi_notify_error(struct burn_drive *, struct command *c,
|
||||||
unsigned char *sense, int senselen, int flag);
|
unsigned char *sense, int senselen, int flag);
|
||||||
|
|
||||||
|
/* ts A70519 */
|
||||||
|
int scsi_init_command(struct command *c, unsigned char *opcode, int oplen);
|
||||||
|
|
||||||
#endif /*__SPC*/
|
#endif /*__SPC*/
|
||||||
|
@ -353,9 +353,13 @@ int burn_track_set_sectors(struct burn_track *t, int sectors)
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ts A70218 */
|
/* ts A70218 , API since A70328 */
|
||||||
int burn_track_set_size(struct burn_track *t, off_t size)
|
int burn_track_set_size(struct burn_track *t, off_t size)
|
||||||
{
|
{
|
||||||
|
if (t->source == NULL)
|
||||||
|
return 0;
|
||||||
|
if (t->source->set_size == NULL)
|
||||||
|
return 0;
|
||||||
t->open_ended = (size <= 0);
|
t->open_ended = (size <= 0);
|
||||||
return t->source->set_size(t->source, size);
|
return t->source->set_size(t->source, size);
|
||||||
}
|
}
|
||||||
|
@ -128,9 +128,14 @@ void toc_find_modes(struct burn_drive *d)
|
|||||||
if (e && !(e->control & 4)) {
|
if (e && !(e->control & 4)) {
|
||||||
t->mode = BURN_AUDIO;
|
t->mode = BURN_AUDIO;
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
|
t->mode = BURN_MODE1;
|
||||||
|
/* ts A70519 : this does not work with Linux 2.4 USB because one cannot
|
||||||
|
predict the exact dxfer_size without knowing the sector type.
|
||||||
mem.sectors = 1;
|
mem.sectors = 1;
|
||||||
d->read_sectors(d, lba, mem.sectors, &o, &mem);
|
d->read_sectors(d, lba, mem.sectors, &o, &mem);
|
||||||
t->mode = sector_identify(mem.data);
|
t->mode = sector_identify(mem.data);
|
||||||
|
*/
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -51,6 +51,7 @@ struct command
|
|||||||
unsigned char opcode[16];
|
unsigned char opcode[16];
|
||||||
int oplen;
|
int oplen;
|
||||||
int dir;
|
int dir;
|
||||||
|
int dxfer_len;
|
||||||
unsigned char sense[128];
|
unsigned char sense[128];
|
||||||
int error;
|
int error;
|
||||||
int retry;
|
int retry;
|
||||||
@ -117,8 +118,6 @@ struct burn_format_descr {
|
|||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#define LIBBURN_SG_MAX_SIBLINGS 16
|
|
||||||
|
|
||||||
/** Gets initialized in enumerate_common() and burn_drive_register() */
|
/** Gets initialized in enumerate_common() and burn_drive_register() */
|
||||||
struct burn_drive
|
struct burn_drive
|
||||||
{
|
{
|
||||||
@ -225,6 +224,21 @@ struct burn_drive
|
|||||||
struct buffer *buffer;
|
struct buffer *buffer;
|
||||||
struct burn_progress progress;
|
struct burn_progress progress;
|
||||||
|
|
||||||
|
/* ts A70711 : keeping an eye on the drive buffer */
|
||||||
|
off_t pessimistic_buffer_free;
|
||||||
|
int pbf_altered;
|
||||||
|
int wait_for_buffer_free;
|
||||||
|
int nominal_write_speed;
|
||||||
|
unsigned wfb_min_usec;
|
||||||
|
unsigned wfb_max_usec;
|
||||||
|
unsigned wfb_timeout_sec;
|
||||||
|
unsigned wfb_min_percent;
|
||||||
|
unsigned wfb_max_percent;
|
||||||
|
unsigned pessimistic_writes;
|
||||||
|
unsigned waited_writes;
|
||||||
|
unsigned waited_tries;
|
||||||
|
unsigned waited_usec;
|
||||||
|
|
||||||
volatile int cancel;
|
volatile int cancel;
|
||||||
volatile enum burn_drive_status busy;
|
volatile enum burn_drive_status busy;
|
||||||
/* transport functions */
|
/* transport functions */
|
||||||
|
@ -875,6 +875,14 @@ int burn_disc_init_write_status(struct burn_write_opts *o,
|
|||||||
d->progress.buffered_bytes = 0;
|
d->progress.buffered_bytes = 0;
|
||||||
d->progress.buffer_min_fill = 0xffffffff;
|
d->progress.buffer_min_fill = 0xffffffff;
|
||||||
|
|
||||||
|
/* ts A70711 */
|
||||||
|
d->pessimistic_buffer_free = 0;
|
||||||
|
d->pbf_altered = 0;
|
||||||
|
d->pessimistic_writes = 0;
|
||||||
|
d->waited_writes = 0;
|
||||||
|
d->waited_tries = 0;
|
||||||
|
d->waited_usec = 0;
|
||||||
|
|
||||||
/* Set eventual media fill up for last track only */
|
/* Set eventual media fill up for last track only */
|
||||||
for (sx = 0; sx < disc->sessions; sx++)
|
for (sx = 0; sx < disc->sessions; sx++)
|
||||||
for (tx = 0 ; tx < disc->session[sx]->tracks; tx++) {
|
for (tx = 0 ; tx < disc->session[sx]->tracks; tx++) {
|
||||||
@ -1075,9 +1083,31 @@ int burn_disc_close_track_dvd_minus_r(struct burn_write_opts *o,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* ts A70229 */
|
||||||
|
int burn_disc_finalize_dvd_plus_r(struct burn_write_opts *o)
|
||||||
|
{
|
||||||
|
struct burn_drive *d = o->drive;
|
||||||
|
|
||||||
|
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||||
|
0x00000002,
|
||||||
|
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
|
||||||
|
"Finalizing DVD+R ...", 0, 0);
|
||||||
|
|
||||||
|
/* CLOSE SESSION, 101b, Finalize with minimal radius */
|
||||||
|
d->close_track_session(d, 2, 1); /* (2<<1)|1 = 5 */
|
||||||
|
|
||||||
|
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||||
|
0x00000002,
|
||||||
|
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
|
||||||
|
"... finalizing DVD+R done ", 0, 0);
|
||||||
|
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ts A70226 */
|
/* ts A70226 */
|
||||||
int burn_disc_close_track_dvd_plus_r(struct burn_write_opts *o,
|
int burn_disc_close_track_dvd_plus_r(struct burn_write_opts *o,
|
||||||
struct burn_session *s, int tnum)
|
struct burn_session *s, int tnum, int is_last_track)
|
||||||
{
|
{
|
||||||
struct burn_drive *d = o->drive;
|
struct burn_drive *d = o->drive;
|
||||||
char msg[80];
|
char msg[80];
|
||||||
@ -1093,8 +1123,11 @@ int burn_disc_close_track_dvd_plus_r(struct burn_write_opts *o,
|
|||||||
|
|
||||||
/* Each session becomes a single logical track. So to distinguish them,
|
/* Each session becomes a single logical track. So to distinguish them,
|
||||||
it is mandatory to close the session together with each track. */
|
it is mandatory to close the session together with each track. */
|
||||||
d->close_track_session(d, 1, 0); /* CLOSE SESSION, 010b */
|
|
||||||
|
|
||||||
|
if (is_last_track && !o->multi)
|
||||||
|
burn_disc_finalize_dvd_plus_r(o);
|
||||||
|
else
|
||||||
|
d->close_track_session(d, 1, 0); /* CLOSE SESSION, 010b */
|
||||||
d->busy = BURN_DRIVE_WRITING;
|
d->busy = BURN_DRIVE_WRITING;
|
||||||
d->last_track_no++;
|
d->last_track_no++;
|
||||||
return 1;
|
return 1;
|
||||||
@ -1103,7 +1136,7 @@ int burn_disc_close_track_dvd_plus_r(struct burn_write_opts *o,
|
|||||||
|
|
||||||
/* ts A61218 - A70129 */
|
/* ts A61218 - A70129 */
|
||||||
int burn_dvd_write_track(struct burn_write_opts *o,
|
int burn_dvd_write_track(struct burn_write_opts *o,
|
||||||
struct burn_session *s, int tnum)
|
struct burn_session *s, int tnum, int is_last_track)
|
||||||
{
|
{
|
||||||
struct burn_track *t = s->track[tnum];
|
struct burn_track *t = s->track[tnum];
|
||||||
struct burn_drive *d = o->drive;
|
struct burn_drive *d = o->drive;
|
||||||
@ -1189,7 +1222,8 @@ int burn_dvd_write_track(struct burn_write_opts *o,
|
|||||||
goto ex;
|
goto ex;
|
||||||
} else if (d->current_profile == 0x1b || d->current_profile == 0x2b) {
|
} else if (d->current_profile == 0x1b || d->current_profile == 0x2b) {
|
||||||
/* DVD+R , DVD+R/DL */
|
/* DVD+R , DVD+R/DL */
|
||||||
ret = burn_disc_close_track_dvd_plus_r(o, s, tnum);
|
ret = burn_disc_close_track_dvd_plus_r(o, s, tnum,
|
||||||
|
is_last_track);
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
goto ex;
|
goto ex;
|
||||||
}
|
}
|
||||||
@ -1268,7 +1302,7 @@ int burn_disc_close_session_dvd_minus_r(struct burn_write_opts *o,
|
|||||||
|
|
||||||
/* ts A61218 */
|
/* ts A61218 */
|
||||||
int burn_dvd_write_session(struct burn_write_opts *o,
|
int burn_dvd_write_session(struct burn_write_opts *o,
|
||||||
struct burn_session *s)
|
struct burn_session *s, int is_last_session)
|
||||||
{
|
{
|
||||||
int i,ret;
|
int i,ret;
|
||||||
struct burn_drive *d = o->drive;
|
struct burn_drive *d = o->drive;
|
||||||
@ -1276,7 +1310,8 @@ int burn_dvd_write_session(struct burn_write_opts *o,
|
|||||||
/* >>> open_session ? */
|
/* >>> open_session ? */
|
||||||
|
|
||||||
for (i = 0; i < s->tracks; i++) {
|
for (i = 0; i < s->tracks; i++) {
|
||||||
ret = burn_dvd_write_track(o, s, i);
|
ret = burn_dvd_write_track(o, s, i,
|
||||||
|
is_last_session && i == (s->tracks - 1));
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -1428,24 +1463,6 @@ int burn_disc_setup_dvd_plus_r(struct burn_write_opts *o,
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/* ts A70229 */
|
|
||||||
int burn_disc_finalize_dvd_plus_r(struct burn_write_opts *o)
|
|
||||||
{
|
|
||||||
struct burn_drive *d = o->drive;
|
|
||||||
|
|
||||||
/* <<< FOR NOW: avoid finalizing media */
|
|
||||||
return 3;
|
|
||||||
|
|
||||||
if (o->multi)
|
|
||||||
return 2;
|
|
||||||
d->busy = BURN_DRIVE_CLOSING_SESSION;
|
|
||||||
/* CLOSE SESSION, 101b, Finalize with minimal radius */
|
|
||||||
d->close_track_session(d, 2, 1); /* (2<<1)|1 = 5 */
|
|
||||||
d->busy = BURN_DRIVE_WRITING;
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* ts A61218 - A70129 */
|
/* ts A61218 - A70129 */
|
||||||
int burn_dvd_write_sync(struct burn_write_opts *o,
|
int burn_dvd_write_sync(struct burn_write_opts *o,
|
||||||
struct burn_disc *disc)
|
struct burn_disc *disc)
|
||||||
@ -1700,7 +1717,8 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
|
|||||||
d->progress.session = i;
|
d->progress.session = i;
|
||||||
d->progress.tracks = disc->session[i]->tracks;
|
d->progress.tracks = disc->session[i]->tracks;
|
||||||
|
|
||||||
ret = burn_dvd_write_session(o, disc->session[i]);
|
ret = burn_dvd_write_session(o, disc->session[i],
|
||||||
|
i == (disc->sessions - 1));
|
||||||
if (ret <= 0)
|
if (ret <= 0)
|
||||||
goto ex;
|
goto ex;
|
||||||
|
|
||||||
@ -1709,12 +1727,6 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
|
|||||||
d->progress.start_sector = 0;
|
d->progress.start_sector = 0;
|
||||||
d->progress.sectors = 0;
|
d->progress.sectors = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (d->current_profile == 0x1b || d->current_profile == 0x2b) {
|
|
||||||
ret = burn_disc_finalize_dvd_plus_r(o);
|
|
||||||
if (ret <= 0)
|
|
||||||
goto ex;
|
|
||||||
}
|
|
||||||
ret = 1;
|
ret = 1;
|
||||||
ex:;
|
ex:;
|
||||||
|
|
||||||
|
@ -8,8 +8,8 @@
|
|||||||
|
|
||||||
libburner is a minimal demo application for the library libburn as provided
|
libburner is a minimal demo application for the library libburn as provided
|
||||||
on http://libburnia.pykix.org . It can list the available devices, can
|
on http://libburnia.pykix.org . It can list the available devices, can
|
||||||
blank a CD-RW or DVD-RW, can format a DVD-RW, and can burn to CD-R, CD-RW,
|
blank a CD-RW or DVD-RW, can format a DVD-RW, can burn to CD-R, CD-RW, DVD-R,
|
||||||
DVD+RW, DVD-RAM or DVD-RW. Not supported yet: DVD+R [DL].
|
DVD+R, DVD+RW, DVD-RAM or DVD-RW. Not supported yet: double layer media.
|
||||||
|
|
||||||
It's main purpose, nevertheless, is to show you how to use libburn and also
|
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
|
to serve the libburnia team as reference application. libburner.c does indeed
|
||||||
@ -350,7 +350,7 @@ int libburner_format_row(struct burn_drive *drive)
|
|||||||
|
|
||||||
/** Brings preformatted track images (ISO 9660, audio, ...) onto media.
|
/** Brings preformatted track images (ISO 9660, audio, ...) onto media.
|
||||||
To make sure a data image is fully readable on any Linux machine, this
|
To make sure a data image is fully readable on any Linux machine, this
|
||||||
function adds 300 kB of padding to the (usualy single) track.
|
function adds 300 kiB of padding to the (usualy single) track.
|
||||||
Audio tracks get padded to complete their last sector.
|
Audio tracks get padded to complete their last sector.
|
||||||
|
|
||||||
In case of external signals expect abort handling of an ongoing burn to
|
In case of external signals expect abort handling of an ongoing burn to
|
||||||
@ -378,7 +378,7 @@ int libburner_payload(struct burn_drive *drive,
|
|||||||
|
|
||||||
if (all_tracks_type != BURN_AUDIO) {
|
if (all_tracks_type != BURN_AUDIO) {
|
||||||
all_tracks_type = BURN_MODE1;
|
all_tracks_type = BURN_MODE1;
|
||||||
/* a padding of 300 kB helps to avoid the read-ahead bug */
|
/* a padding of 300 kiB helps to avoid the read-ahead bug */
|
||||||
padding = 300*1024;
|
padding = 300*1024;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
133
test/open-cd-excl.c
Normal file
133
test/open-cd-excl.c
Normal file
@ -0,0 +1,133 @@
|
|||||||
|
/*
|
||||||
|
* open-cd-excl.c --- This program tries to open a block device
|
||||||
|
* by various exclusive and non-exclusive gestures in order to explore
|
||||||
|
* their impact on running CD/DVD recordings.
|
||||||
|
*
|
||||||
|
* Copyright 2007, by Theodore Ts'o.
|
||||||
|
*
|
||||||
|
* Detail modifications 2007, by Thomas Schmitt.
|
||||||
|
*
|
||||||
|
* %Begin-Header%
|
||||||
|
* This file may be redistributed under the terms of the GNU Public
|
||||||
|
* License.
|
||||||
|
* %End-Header%
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define _GNU_SOURCE /* for O_LARGEFILE *//*ts A70417: or _LARGEFILE64_SOURCE */
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <getopt.h>
|
||||||
|
|
||||||
|
const char *progname;
|
||||||
|
|
||||||
|
static void usage(void)
|
||||||
|
{
|
||||||
|
fprintf(stderr, "Usage: %s [-feirw] device\n", progname);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ts A70417: added parameter do_rdwr */
|
||||||
|
static void init_flock(struct flock *fl, int do_rdwr)
|
||||||
|
{
|
||||||
|
memset(fl, 0, sizeof(struct flock));
|
||||||
|
if (do_rdwr)
|
||||||
|
fl->l_type = F_WRLCK;
|
||||||
|
else
|
||||||
|
fl->l_type = F_RDLCK;
|
||||||
|
fl->l_whence = SEEK_SET;
|
||||||
|
fl->l_start = 0;
|
||||||
|
fl->l_len = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
int main(int argc, char **argv)
|
||||||
|
{
|
||||||
|
struct flock fl;
|
||||||
|
char *device_name;
|
||||||
|
int fd, c, f_opt = 0, do_rdwr = 0, end_immediately = 0;
|
||||||
|
int flags = O_NONBLOCK|O_LARGEFILE;
|
||||||
|
|
||||||
|
progname = argv[0];
|
||||||
|
|
||||||
|
/* ts A70417: added -w , -r , -i */
|
||||||
|
while ((c = getopt (argc, argv, "feirw")) != EOF) {
|
||||||
|
switch (c) {
|
||||||
|
case 'e':
|
||||||
|
flags |= O_EXCL;
|
||||||
|
break;
|
||||||
|
case 'f':
|
||||||
|
f_opt++;
|
||||||
|
break;
|
||||||
|
case 'i':
|
||||||
|
end_immediately = 1;
|
||||||
|
break;
|
||||||
|
case 'r':
|
||||||
|
do_rdwr = 0;
|
||||||
|
break;
|
||||||
|
case 'w':
|
||||||
|
do_rdwr = 1;
|
||||||
|
break;
|
||||||
|
case '?':
|
||||||
|
usage();
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (optind == argc)
|
||||||
|
usage();
|
||||||
|
device_name = argv[optind++];
|
||||||
|
|
||||||
|
/* ts A70417 : made read-write adjustable independently of f_opt */
|
||||||
|
if (do_rdwr) {
|
||||||
|
flags |= O_RDWR;
|
||||||
|
printf("Using O_RDWR\n");
|
||||||
|
} else {
|
||||||
|
flags |= O_RDONLY;
|
||||||
|
printf("Using O_RDONLY\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (flags & O_EXCL)
|
||||||
|
printf("Trying to open %s with O_EXCL ...\n", device_name);
|
||||||
|
fd = open(device_name, flags, 0);
|
||||||
|
if (fd < 0) {
|
||||||
|
perror("open");
|
||||||
|
printf("failed\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (flags & O_EXCL)
|
||||||
|
printf("succeeded\n");
|
||||||
|
|
||||||
|
if (f_opt) {
|
||||||
|
init_flock(&fl, do_rdwr);
|
||||||
|
if (fcntl(fd, F_GETLK, &fl) < 0) {
|
||||||
|
perror("fcntl: F_GETLK: ");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
printf("fcntl lock apparently %sLOCKED\n",
|
||||||
|
(fl.l_type == F_UNLCK) ? "NOT " : "");
|
||||||
|
|
||||||
|
init_flock(&fl, do_rdwr);
|
||||||
|
printf("Trying to grab fcntl lock...\n");
|
||||||
|
if (fcntl(fd, F_SETLK, &fl) < 0) {
|
||||||
|
perror("fcntl: F_SETLK: ");
|
||||||
|
printf("failed\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
printf("succeeded\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ts A70417: added end_immediately */
|
||||||
|
printf("Holding %s open.\n", device_name);
|
||||||
|
usleep(100000);
|
||||||
|
if (end_immediately)
|
||||||
|
exit(0);
|
||||||
|
printf("Press ^C to exit.\n");
|
||||||
|
while (1) {
|
||||||
|
sleep(300);
|
||||||
|
}
|
||||||
|
/* NOTREACHED */
|
||||||
|
return 0;
|
||||||
|
}
|
@ -312,6 +312,11 @@ int telltoc_media(struct burn_drive *drive)
|
|||||||
caps->advised_write_mode == BURN_WRITE_RAW ?
|
caps->advised_write_mode == BURN_WRITE_RAW ?
|
||||||
" (advised)" : "");
|
" (advised)" : "");
|
||||||
printf("\n");
|
printf("\n");
|
||||||
|
printf("Write dummy : ");
|
||||||
|
if (caps->might_simulate)
|
||||||
|
printf("supposed to work with non-RAW modes\n");
|
||||||
|
else
|
||||||
|
printf("will not work\n");
|
||||||
o= burn_write_opts_new(drive);
|
o= burn_write_opts_new(drive);
|
||||||
if (o != NULL) {
|
if (o != NULL) {
|
||||||
burn_write_opts_set_perform_opc(o, 0);
|
burn_write_opts_set_perform_opc(o, 0);
|
||||||
|
Reference in New Issue
Block a user