Compare commits

...

332 Commits

Author SHA1 Message Date
7e01bae7e6 Documented changes and release timestamp 2010-06-11 09:57:58 +00:00
7c0a33420a Updated cdrskin tarball generator 2010-06-11 08:34:07 +00:00
101a8813d5 Made number transition to 0.8.2 2010-06-11 08:32:24 +00:00
3a5acf9989 Branching for libburn release 0.8.2 2010-06-11 07:50:01 +00:00
e9828cddd0 Mentioned Solaris and system dependent drive permission settings 2010-06-10 17:23:23 +00:00
7f0358892a Removed obsolete development remark 2010-06-10 17:09:50 +00:00
bc40ce2876 Implemented block device capacity determination fo Solaris 2010-06-08 20:04:01 +00:00
6674667b7f Handled SCSI status "BUSY" on Solaris 2010-06-08 17:50:33 +00:00
cc4d72bf8b Corrected comment 2010-06-08 17:32:44 +00:00
1eee6ab8a0 New system adapter for Solaris uscsi (tested on snv134, kernel 5.11) 2010-06-07 17:30:54 +00:00
736d8b9019 Reacted on harmless compiler warnings on Solaris 2010-06-07 17:17:53 +00:00
8345eb8a71 Avoiding to resolve /dev/rdsk/cXtYdZs2 drive addresses on Solaris libcdio 2010-06-07 17:16:40 +00:00
cc7548f1c7 Bug fix: SIGSEGV of libcdio system adapter if drive list is empty 2010-05-29 07:44:41 +00:00
edca339338 Eventually including ../config.h generated by autotools 2010-05-16 09:07:42 +00:00
9323cceff1 Bug fix: CD-ROM media got attributed random lead-in and lead-out adresses 2010-05-01 08:29:28 +00:00
8b1b3f08c6 Avoided to create track without toc_entry from "hidden first track" on CD 2010-04-30 18:04:47 +00:00
e332f4a438 Documented changes and release timestamp 2010-04-09 11:13:19 +00:00
960fe6d188 Updated cdrskin tarball generator 2010-04-09 10:59:32 +00:00
92c5f6f998 Made number transition to 0.8.1 2010-04-09 10:57:38 +00:00
2069ffa863 Reporting eventual SCSI sense in sg-linux repeat loop 2010-04-09 09:07:59 +00:00
e787d328c7 Let libburner warn programmers if they forget to set 64 bit off_t 2010-04-04 18:13:45 +00:00
fafc190fd4 Adjusted libcdio system adapter to FreeBSD peculiarities 2010-03-29 10:33:05 +00:00
e6029ae238 Trying to detect FreeBSD ahci devices and to handle others the old way 2010-03-27 17:27:50 +00:00
6e17c59f6b Avoiding to inquire NWA of unwritable media or states 2010-03-27 15:58:05 +00:00
0e777ec688 Had to make ahci change conditional for now: -DLibburn_for_freebsd_ahcI 2010-03-26 08:33:22 +00:00
8dcdb5a87f Changed sg-freebsd.c to work with ahci, advise by Alexander Motin 2010-03-25 11:36:55 +00:00
4f372c00bc Corrected initialization of configure option --enable-dvd-obs-64k 2010-03-17 18:54:10 +00:00
9f6d80d87d Small bug fix about track size with cdrskin -minfo 2010-03-17 18:53:28 +00:00
b33df8fbd5 Documented changes and release timestamp 2010-03-10 13:58:50 +00:00
b4bb522053 Updated cdrskin tarball generator 2010-03-10 13:58:03 +00:00
3289ffd1e6 Made number transition to 0.7.9 2010-03-10 13:56:58 +00:00
196ef37108 Clarifications in API description of burn_set_signal_handling() 2010-03-09 14:01:57 +00:00
cdad7fcd80 Prevented potential memory fault with burn_set_signal_handling() 2010-03-08 09:24:21 +00:00
ed6e2df81b Changed examples burn_set_signal_handling(...,48) to (...,0x30) 2010-03-07 08:15:21 +00:00
ae667ca2e8 Adapted libburner to new advise about signal handling 2010-03-06 13:52:21 +00:00
873e3f5d78 Protected blanker and formatter thread from signals 2010-03-05 18:59:21 +00:00
72f9ff8b8c Removed some debugging printing 2010-03-05 11:15:28 +00:00
eb95f7fc16 Enabled optional use of new signal action 2 with libburn built-in handler 2010-03-05 09:12:44 +00:00
3519b42c14 Introduced alternative signal handling actions 2010-03-05 09:08:16 +00:00
b4e5afd317 Changed burn_abort(0) to burn_abort(-1) 2010-03-04 17:59:42 +00:00
7446ed7daa Showing more patience with temporarily busy drives on Linux 2010-03-04 12:13:04 +00:00
2d40b098e5 Enabled static compile script compile_cdrskin.sh for FreeBSD 2010-03-03 15:29:16 +00:00
ac64aef090 Enabled static compile script compile_cdrskin.sh for FreeBSD 2010-03-03 14:43:21 +00:00
74a68adc6e Adapted cdrskin abort handler to FreeBSD peculiarities 2010-03-03 14:12:22 +00:00
937bc87bfc Enabled patience 0 within burn_abort() 2010-03-03 14:05:07 +00:00
de482489c1 Corrected spelling errors in cdrskin man page 2010-02-28 16:53:09 +00:00
295fa1d526 Bug fix: cdrskin fs=0 lead to SIGSEGV. Regression introduced by revision 2936. 2010-02-28 11:06:02 +00:00
99bba3e98e Added forgotten initialization of a variable 2010-02-28 10:38:15 +00:00
bd3016e085 Corrected optional speed curb for stdio: drives. Was damaged by revision 2903. 2010-02-25 07:04:52 +00:00
dd74364ebb Made burn_set_signal_handling() more suitable for cdrskin 2010-02-22 13:47:17 +00:00
255e5362f9 Avoided random percentage display at start of blanking 2010-02-17 14:12:23 +00:00
471a0d0058 Bug fix on FreeBSD: Piped input was falsely attributed a small fixed size 2010-02-16 19:40:07 +00:00
f5b556db47 Changed a comment in libburn/crc.h 2010-02-15 12:57:38 +00:00
c12bbff7d1 Created opportunity to omit source module libburn/crc.c 2010-02-14 17:17:04 +00:00
6db992e646 Added or adjusted copyright and license statements in single files 2010-02-14 08:45:14 +00:00
bd017a108e Changed docs and comments to "GNU/Linux" where appropriate 2010-02-12 21:26:46 +00:00
3a76f9245f Changed system adapter id and some remarks from "Linux" to "GNU/Linux" 2010-02-12 17:30:59 +00:00
580ca08cc5 Forcing use of /usr/local on FreeBSD by LDFLAGS and CPPFLAGS 2010-02-04 08:31:31 +00:00
a6bd4c24db Updated cdrskin tarball generator 2010-01-23 10:44:04 +00:00
54005cb60e Lifted ban to derive GPLv3, extended copyright range to 2010 2010-01-23 10:42:52 +00:00
15fbe0a7ea Made number transition to 0.7.7 2010-01-23 10:40:11 +00:00
da1d260753 Learned how to inquire size of disk-like FreeBSD devices 2010-01-21 10:46:04 +00:00
95865ee34d Changed man page example from -toc to -minfo 2010-01-21 10:38:56 +00:00
eb8b8faa3b Changed a comment in sg-linux.c 2010-01-18 10:32:36 +00:00
39fd8b922d New OS adapter burn_os_is_2k_seekrw() replaces S_ISBLK() with pseudo-drives 2010-01-16 12:51:24 +00:00
7ead54c8b9 Implemented adivisory FreeBSD drive locking via flock(2) 2010-01-15 18:25:14 +00:00
2a85fc7d91 Provisory rejection of FreeBSD ATAPI drives in sg-libcdio 2010-01-14 16:06:17 +00:00
1e42a76415 Giving up drive probing by mode page sending 2010-01-14 16:04:57 +00:00
734759190a Carified in libburner.c that apps must use 64 bit off_t. 2010-01-14 14:09:30 +00:00
16ffa10831 Carified in libburner.c that apps must use 64 bit off_t. 2010-01-14 14:01:13 +00:00
cdfc357064 Carified that apps must use 64 bit off_t or the lib must be tweaked. 2010-01-13 17:14:14 +00:00
df612390d3 Adaptions after encounter with FreeBSD 8.0 2010-01-13 07:45:07 +00:00
77971f3680 Experimentally regard FreeBSD /dev/da[0-9] and /dev/cd[0-9] as block device 2010-01-13 07:38:56 +00:00
5c75d583d7 Fixed typos in MMC cookbook 2010-01-12 16:51:48 +00:00
2ff03841d7 Corrected free capacity measurement of stdio: drives in regular files 2010-01-12 16:50:44 +00:00
a88745c82e Revoked asynchronous eject, as we cannot distinguish out from unready 2010-01-09 14:32:51 +00:00
96167b3d8e Better error message with unknown SCSI error codes 2010-01-09 14:25:19 +00:00
1ca38962d4 Forgot to forward sense reply to higher levels 2010-01-09 14:18:55 +00:00
80bcabfd57 Enlarged buffer size of libcdio adapter on Linux to 64k 2010-01-04 13:52:57 +00:00
d9239aeafc Avoiding stream recording on BD if not 64 kB buffer 2010-01-04 13:49:05 +00:00
758a197d06 Enabled block device size recognition with sg-libcdio on Linux 2010-01-01 12:43:15 +00:00
ed972271ec Bug fix: with non-Linux adapters there were 0 readable bytes on block devices 2010-01-01 12:39:20 +00:00
0544ac8cd3 Silenced libcdio warnings 2009-12-30 20:08:51 +00:00
12a2be8d86 Making use of new libcdio capability to obtain SCSI address tuple on Linux 2009-12-30 15:40:10 +00:00
509db68d82 Adaptions for Debian kfreebsd requested by Petr Salinger 2009-12-29 22:43:35 +00:00
00ed59f34e Experimentally enabled FreeBSD system adapter for Debian kfreebsd 2009-12-29 13:31:56 +00:00
2b8e8c2521 Corrected a mode page size computation error which for now had no bad effect 2009-12-29 11:57:21 +00:00
e3ff0bb0f6 Incremented middle .so number 2009-12-29 11:55:48 +00:00
8efb24ca6d Reporting system adapter id with cdrskin -version 2009-12-27 14:46:01 +00:00
d53c5db98e Extended sg-API by sg_shutdown(), sg_dispose_drive(), sg_id_string() 2009-12-27 14:45:05 +00:00
0320b7bf2a Shorter sg_initialize message with sg-libcdio 2009-12-27 10:22:11 +00:00
cee271f9cb Showing libburn users drive name link targets, using in libcdio its own names 2009-12-27 09:20:10 +00:00
c2a3e3677d Reacted on some doxygen warnings of Debian hurd build 2009-12-26 22:25:45 +00:00
fc3445215b Reporting burn_scsi_transport_id() in cdrskin as debug message 2009-12-26 19:35:42 +00:00
4ce8bd45cf Added os-dummy.h and sg-dummy.h to libburn tarball 2009-12-26 08:49:59 +00:00
08169d63bc New API function burn_scsi_transport_id() 2009-12-26 08:01:35 +00:00
e13b6369ba New internal sg-API function sg_initialize() 2009-12-25 22:37:57 +00:00
d3988dd74b Adapted to libcdio-0.83 and its runtime version telling 2009-12-25 20:55:37 +00:00
ef42052900 Added PKG_CHECK_MODULES for libcdio-0.82 (must become 0.83 when released) 2009-12-25 14:40:16 +00:00
240afa7c3a Resolving symbolic links in libcdio drive list 2009-12-25 14:31:55 +00:00
5b72e5d06e Commited file forgotten with rev 2960 2009-12-25 10:13:06 +00:00
4aa08e32ff Option -use_libcdio for cdrskin development compile script 2009-12-25 10:12:22 +00:00
eb34561262 Making use of libcdio function mmc_get_cmd_scsi_sense() 2009-12-24 17:04:40 +00:00
dd85e37ac8 Experimental SCSI transport adapter via GNU libcdio 2009-12-19 14:34:48 +00:00
e566340261 Moved sg_log_cmd() to spc.c scsi_log_cmd() 2009-12-19 14:23:30 +00:00
7e86db207c Corrected CDB length of command 55h MODE SELECT from 12 to 10 2009-12-19 13:59:09 +00:00
a30ecd1abb Mentioned in cookbook the change about TAO close track 2009-12-16 07:39:39 +00:00
45b28b6c31 Documented changes and release timestamp 2009-12-07 07:56:32 +00:00
afedcdd72b Updated cdrskin tarball generator 2009-12-07 07:55:25 +00:00
b8a98e0728 Made number transition to 0.7.5 2009-12-07 07:54:24 +00:00
b238ad5a51 Now default in cdrskin: use of libburn fifo with DVD and BD single track 2009-12-06 09:37:33 +00:00
28f4454a9d Some clarifications about the Linux throughput problem 2009-12-06 07:45:00 +00:00
cb8c23ed5a Some clarifications about the GH22LS30 problem 2009-12-06 07:32:38 +00:00
54bb1ab395 Converted stderr experiment messages to DEBUG messages 2009-12-05 14:35:41 +00:00
872068ba7c Made effect of macro Libburn_pioneer_dvr_216d_read_buf_caP unconditional 2009-12-05 14:22:28 +00:00
2bd800ed14 Bug fix: SIGSEGV with LG GH22LS30 when inquiring media product id 2009-12-05 11:17:13 +00:00
da0b3b3939 Gave up CLOSE TRACK with CD TAO burn runs 2009-12-02 10:29:45 +00:00
93aa6ccc6f Documented meaning of START/STOP UNIT bits 2009-11-30 10:00:34 +00:00
d6edfc9961 Using mmap() by default for allocating read buffers 2009-11-28 12:23:20 +00:00
2945ab61d7 Compiler option -use_libburn_fifo to switch non-CD from cdrfifo to libburn fifo 2009-11-26 21:12:57 +00:00
d35f7d0de1 New API calls burn_fifo_get_statistics(), burn_fifo_next_interval() 2009-11-26 14:43:38 +00:00
e335aa26b4 New API call burn_fifo_fill() 2009-11-25 16:00:33 +00:00
496d794bcd Gave up call burn_os_close_track_src() introduced by rev 2920 2009-11-25 12:21:12 +00:00
c88a428d5e Gave up cdrskin specific O_DIRECT compile option 2009-11-23 19:31:32 +00:00
dc8ecdd77e New API calls burn_os_open_track_src() , burn_os_alloc_buffer() 2009-11-23 18:56:18 +00:00
259d1cd2b7 Bug fix: DVD DAO track size was rounded up much too generously 2009-11-22 20:52:40 +00:00
7fddf9ffc5 Enabled cdrskin O_DIRECT with fs=0 2009-11-21 19:15:52 +00:00
6109a7bc08 Longer READ BUFFER CAPACITY interval with DVD/BD writing 2009-11-21 19:14:05 +00:00
9b28a9b272 Avoided use of uninitialized variable 2009-11-20 17:57:34 +00:00
f39ff2c2f6 Experiment about SG_FLAG_DIRECT_IO 2009-11-20 13:48:44 +00:00
c8e0472637 Reserving enough track space for 64 kB write chunks 2009-11-18 18:56:14 +00:00
acb2f3b173 Split automatic drive start function from mmc_function_spy() 2009-11-18 12:25:57 +00:00
504677de4f Corrected help text of cdrskin static compile script 2009-11-17 16:54:52 +00:00
ae8f65e956 Revoked usage of libburn_libburn_la_CFLAGS in Makefile.am (ugly .o names) 2009-11-17 09:34:46 +00:00
c2c10e263e Updated build instructions of libburn and cdrskin 2009-11-16 18:00:30 +00:00
43761c55ef New compile_cdrskin.sh option -dvd_obs_64k, adapted to new .o names of libburn 2009-11-16 16:55:58 +00:00
b28165f10b Configure options --enable-cdrskin-fifo-odirect, --enable-dvd-obs-64k 2009-11-16 16:53:07 +00:00
25489521bb New options dvd_obs= and stdio_fsync= 2009-11-15 16:49:04 +00:00
79a33ca2ac New API calls burn_write_opts_set_dvd_obs(), burn_write_opts_set_stdio_fsync() 2009-11-15 15:30:26 +00:00
738b83ac03 New compile_cdrskin.sh option -o_direct (Linux only) 2009-11-15 15:24:21 +00:00
677b007100 Corrected an outdated remark 2009-11-15 15:21:04 +00:00
0fc685fc85 Man page entry and help text for option -V 2009-11-12 19:34:58 +00:00
ca2cae9b0a Implemented option -V for logging of SCSI commands 2009-11-12 18:01:26 +00:00
055876d6b7 Macro Libburn_pioneer_dvr_216d_dummy_probe_wM for omitting write mode probe 2009-11-12 18:00:01 +00:00
9160b1dcbb Workaround for Pioneer DVR-216D refusal to eject 2009-11-12 17:56:18 +00:00
0f37170759 Made SCSI logger permanent and controllable via API call 2009-11-12 17:54:06 +00:00
ce3d4dbed3 Updated cdrskin home page about DVR-216D workaround 2009-11-11 10:57:30 +00:00
f9acd4ee3d Silenced a compiler warning about potentially uninitialized variable 2009-11-11 10:49:11 +00:00
d118b82a13 Reporting number of pending bytes while thanking for patience in -vvv mode 2009-11-11 10:07:03 +00:00
76a4c0ac44 Increased stdio flush interval from 1 MB to 16 MB 2009-11-11 10:05:56 +00:00
83f80364c5 Hopefully solved the endless burn problem with Pioneer DVR-216D 2009-11-10 20:32:59 +00:00
9064b56c56 Avoiding START UNIT before the drive gets released 2009-11-10 12:21:43 +00:00
405e6b020e Made SCSI command log more complete and more readable 2009-11-08 11:12:23 +00:00
ffe80264c7 Corrected allocation length with GET CONFIGURATION 2009-11-08 11:08:19 +00:00
d158e7f456 Test macros for double START UNIT and SET CD SPEED 2009-11-05 17:03:01 +00:00
4384b0c006 Test macro for SEND OPC INFORMATION before DVD-R track 2009-11-04 08:46:17 +00:00
e78353b7dd Test macro for SL_V in mode page 05 2009-11-03 18:45:08 +00:00
3c2ad1be42 Test macros for finding reason of stall problem with Pioneer DVD-216D on DVD-R 2009-10-30 13:45:26 +00:00
937a226543 Bug fix: Closed memory leak with failure to open device file under FreeBSD. Thanks to George Danchev. 2009-10-27 10:09:31 +00:00
cca24711b8 Bug fix: burn_drive->disc_id or burn_drive->disc_app_code altered by stray 0. Thanks to George Danchev. 2009-10-27 10:06:43 +00:00
e646686145 More optimizations with parity computation 2009-10-20 16:14:14 +00:00
f3070d2e71 Optimizations with parity computation, clarification about nature of logarithms 2009-10-19 11:56:25 +00:00
e0c501a59a Re-implemented ECMA-130 P-parity, Q-parity and scrambling for BURN_WRITE_RAW 2009-10-17 13:17:53 +00:00
39a7d18266 Re-implemented ECMA-130 P-parity, Q-parity and scrambling for BURN_WRITE_RAW 2009-10-17 13:17:06 +00:00
de8ecab9b4 Documented changes and release timestamp 2009-10-12 11:00:23 +00:00
e9a6b9c36d Updated cdrskin tarball generator 2009-10-12 10:59:24 +00:00
e65ccb2b5e Made number transition to 0.7.3 2009-10-12 10:52:37 +00:00
96a5a2a28a Made -minfo subtract 2 from track size if "Data" and last 2 blocks unreadable 2009-10-09 20:06:25 +00:00
ca97df9798 Made read_capacity error message of burn_read_data() depending on flag bit1 2009-10-09 20:03:06 +00:00
22905f7349 Made -minfo stupidly report overwriteable media as "erasable" and "complete" 2009-10-09 12:37:38 +00:00
a318da9463 Determining read capacity for DVD-RAM 2009-10-09 12:35:42 +00:00
3c69b684a8 Fixed CD TAO multi-track -dummy bug reported by Philippe Rouquier 2009-10-04 15:11:35 +00:00
4457061656 Restricted retry to the timeout for single SCSI commands (200 seconds) 2009-09-22 19:26:57 +00:00
758f5a5c1e Revoked instruction to retry STOP UNIT 2009-09-22 19:24:41 +00:00
c8c4da8e8e Mentioned need for 2056 byte fifo chunks with burn_track_set_cdxa_conv() 2009-09-20 11:19:11 +00:00
4fdebcae9f Refusing to read beyond media_read_capacity 2009-09-18 16:18:37 +00:00
82ee4c8788 Fixing SIGSEGV with CD SAO introduced with revision 2808 2009-09-18 16:16:56 +00:00
ad4a286736 Evaluating read capacity with role 2 drives (regular files and block devices) 2009-09-13 09:49:50 +00:00
9017f0716f Updated cdrskin web page 2009-09-12 13:42:27 +00:00
7973546a4c Interpreting options -mode2, -xa, -xa1, -xa2 but producing CD-ROM Mode 1 tracks 2009-09-11 12:08:59 +00:00
2e6f83b3b3 New API call burn_track_set_cdxa_conv() 2009-09-11 11:53:36 +00:00
fdd190b65c Removed Media summary from -minfo because of incompatible counting rules 2009-09-10 07:11:54 +00:00
97ac17512f Silenced compiler warning 2009-09-09 17:42:31 +00:00
28a1b4dcba Emulation of some -minfo output 2009-09-09 17:33:48 +00:00
b724ab2130 New struct burn_toc_entry extension for Last Recorded Address 2009-09-09 15:38:47 +00:00
567beb1d9f Correction with erasable bit of burn_disc_get_cd_info() 2009-09-09 13:39:27 +00:00
eb62395e41 New API call burn_disc_get_cd_info() 2009-09-09 12:52:07 +00:00
1d6c97c79f Avoided to read third sixpack of manufacturer bytes with DVD-R media 2009-09-06 11:20:18 +00:00
5e4c1cf967 Corrected misformatted manufacturer strings of DVD- media 2009-09-06 09:37:23 +00:00
719096b0a7 Changed new API call burn_get_media_product_id() to burn_disc_get_media_id() 2009-09-06 09:25:52 +00:00
75dca6c6e9 Made recognition of CD media codes work in burn_guess_manufacturer() 2009-09-06 09:22:26 +00:00
1ef3a24885 "Manufacturer:", "Media type:" as cdrecord, own "Product Id:" and "Producer:" 2009-09-05 16:51:57 +00:00
790b4f31ee Introduced flag bit0 for API call burn_get_media_product_id() 2009-09-05 16:50:41 +00:00
9362a0240b Re-enabled output of product id and manufacturer 2009-09-05 13:19:01 +00:00
82e884c432 Made cdrskin/compile_cdrskin.sh -libburn_0_7_0 work again 2009-09-05 12:08:43 +00:00
f6d6dcfad0 Closed a small memory leak with drive inquiry 2009-09-05 11:50:09 +00:00
970ae46cfa Silenced a valgrind warning caused by not recognizing side effects of a ioctl 2009-09-05 11:42:25 +00:00
693784cbf5 Made product ID surely a single printable word 2009-09-05 11:29:44 +00:00
3a98bc52f9 Adjusted column width of media summary message 2009-09-05 07:24:06 +00:00
6038928fe4 Adjusted column width of media info messages 2009-09-04 20:43:29 +00:00
2e547b0bba Updated media info documentation 2009-09-04 20:41:08 +00:00
e968e81409 Option -atip now reports Product Id and Manufacturer for most CD, DVD, BD types 2009-09-04 20:22:54 +00:00
557299d350 New API calls burn_get_media_product_id() and burn_guess_manufacturer() 2009-09-04 20:21:55 +00:00
6642342274 New API call burn_guess_cd_manufacturer() 2009-09-02 13:32:17 +00:00
40b3380d4d Removed lec.c from libburn 2009-09-02 13:14:23 +00:00
3b018684c7 New option --long_toc, now printing media summary at end of TOC 2009-09-01 13:34:23 +00:00
96beb44455 Aligned the output columns of cdrskin --devices 2009-09-01 11:38:57 +00:00
9805ce7534 Disabled code using libburn/lec.c, removed lec.c from libburn 2009-09-01 09:57:14 +00:00
407471898c Disabled code using libburn/lec.c, removed lec.c from libburn 2009-09-01 09:56:51 +00:00
cf9a2031a4 Disabled write mode -raw96r 2009-09-01 08:25:01 +00:00
d9fc6cc275 Documented changes and release timestamp 2009-08-27 14:41:38 +00:00
78713d8912 Updated cdrskin tarball generator 2009-08-27 14:39:33 +00:00
169963eced Made number transition to development version 0.7.1 2009-08-27 14:38:24 +00:00
22c187cd61 Implemented automatic START UNIT after STOP UNIT before any other SCSI command 2009-08-24 20:24:39 +00:00
b900831914 Made burn_drive_snooze() safe for emulated drives 2009-08-24 16:15:46 +00:00
654d71ef07 New API call burn_drive_snooze() 2009-08-24 13:10:53 +00:00
0571f4dc2e Adapted to pitfalls of U3 memory sticks which appear as CD-ROM drives 2009-08-23 13:08:19 +00:00
ff23614200 Listing all profiles with cdrskin -v -atip 2009-08-15 13:36:51 +00:00
c59300b27a New API calls burn_drive_get_all_profiles(), burn_obtain_profile_name() 2009-08-15 13:32:56 +00:00
635996a327 Added test code about output blocks size as comment. 2009-08-15 13:30:42 +00:00
93287896a6 Documented changes and release timestamp 2009-07-14 13:39:08 +00:00
4da88193fa Updated cdrskin tarball generator 2009-07-14 13:38:19 +00:00
3091eeb9c9 Made number transition and activated development documentation 2009-07-14 13:37:11 +00:00
19a668a48e Timestamp for revision 2691 2009-07-07 19:17:40 +00:00
6ceabaff32 configure options --enable-libdir-pkgconfig and --enable-pkgconfig-path=DIR 2009-07-07 19:12:18 +00:00
b65b852c15 Retrying 3 times on EBUSY drives with generous usleep intervals 2009-06-14 09:49:47 +00:00
1ccedd5572 Bug fix: No usable media was detected with old MMC-1 drives 2009-06-03 18:53:57 +00:00
473e205c9e Bug fix: Old MMC-1 drives were rejected because of mode page 2Ah length 2009-06-03 08:58:18 +00:00
2522bebfbd Avoided to enumerate faulty drive objects 2009-06-02 17:21:43 +00:00
8276611468 Avoided SIGSEGV if no drives were found by scan 2009-06-02 16:30:06 +00:00
38994b62c0 Rectified use of burn_drive.mdata->valid 2009-06-02 16:28:33 +00:00
474c4cddd7 Made -scanbus work with SCSI bus numbers like 85 (USB, kernel 2.6.18.2) 2009-05-17 14:42:52 +00:00
b0b4bc57f8 Documented changes and release timestamp 2009-05-07 18:17:54 +00:00
b97fa7a451 Updated cdrskin tarball generator 2009-05-07 18:16:55 +00:00
8aca8e9921 Made number transition and activated development documentation 2009-05-07 18:15:47 +00:00
15b31b121a Mentioned BD were it was missing 2009-05-07 18:12:32 +00:00
e5632de786 Bug fix: Device scan stalled on FreeBSD. Ticket 148 jwele 2009-04-30 07:08:23 +00:00
91e3a2f3f7 Replaced 8 blanks by a tab 2009-04-30 06:59:35 +00:00
0ffc4bd19b Marked alleged use of uninitialized memory reported by valgrind 2009-04-30 06:56:47 +00:00
9cb4e4281e Bug fix: burn_abort() did not work with broken output pipe (since rev 2514) 2009-03-18 17:25:00 +00:00
f87747802a Human readable error messages for asc=08 "Logical unit communication failure" 2009-03-18 12:45:59 +00:00
4626304e39 Get on FreeBSD pkgconfigdir=.../libdata , on Linux and others: .../lib 2009-03-16 19:07:45 +00:00
d19abc1940 Documented changes and release timestamp 2009-03-13 14:15:46 +00:00
5ef7b4b445 Updated cdrskin tarball generator 2009-03-13 14:10:09 +00:00
033107b436 Made libburn number transition to 0.6.5 2009-03-13 14:03:13 +00:00
635405da8f Reacted on compiler warnings of SchilliX-0.6.7 (based on Solaris 5.11) 2009-03-08 14:01:10 +00:00
aafa543391 Lifted the ban on operating systems other than Linux and FreeBSD 2009-03-05 14:53:00 +00:00
8594cd96bc Making optional use of statvfs() in sg-dummy 2009-03-03 09:20:53 +00:00
b07c83ed86 Added a dummy function with loud compiler warning to sg.c dummy case 2009-03-02 20:01:37 +00:00
d74b1a2008 Fixed a race condition on abort with stdio writing which could cause SIGSEGV 2009-03-02 19:33:47 +00:00
8c56ca131f New operating system adapter "dummy" for stdio on POSIX-like systems 2009-03-02 17:01:21 +00:00
53e4483460 New stream_recording mode with start number 2009-02-27 21:17:05 +00:00
591c385489 New API function burn_drive_set_stream_recording() 2009-02-27 14:30:57 +00:00
b0f1f67495 Forgotten version leap to 0.6.3 in libburn.h 2009-02-20 13:23:57 +00:00
6139fb32dd Updated cdrskin tarball generator 2009-02-20 12:52:15 +00:00
01ed4729bd Made number transition to 0.6.3 2009-02-20 12:50:12 +00:00
350ac05bfd Human readable error messages with asynchronous SCSI errors 2009-02-19 19:28:16 +00:00
5f55a436e8 Mentioned hald as possibly conflicting service 2009-02-04 10:56:11 +00:00
3baaa886be Linking with $LIBBURN_ARCH_LIBS to get -lcam on FreeBSD 2009-02-04 10:28:26 +00:00
d4147e72f0 Mentioned the need for 64 bit file i/o 2009-01-27 12:10:39 +00:00
116798e081 Updated cookbook about BD-R media 2009-01-11 13:45:09 +00:00
7cc43c44e9 Prepared eventual closing of spoiled BD-R media by a pseudo write run 2009-01-11 10:28:05 +00:00
de0b3dd469 Preventing a possible bug with a burn run of more than one session at once 2009-01-09 16:17:25 +00:00
596d5bc5b0 Recognizing BD-R media spoiled by the close bug and handling them as appendable 2009-01-09 09:59:59 +00:00
867093d7d4 Mentioned bug fix and pl01 2009-01-07 15:50:05 +00:00
47dd4d8c09 Bug fix: BD-R were not correctly finalized 2009-01-07 15:44:30 +00:00
01a825310e Clarification about one-time DVD and BD media 2009-01-07 15:36:51 +00:00
96043eddf5 Complaining and refusing more early with unformatted BD-RE 2009-01-06 13:53:01 +00:00
5a65d6fa07 Complaining and refusing more early with unformatted BD-RE 2009-01-06 12:28:20 +00:00
aca01b88f3 Error texts for ASC 73 : power calibration and program memory 2009-01-06 12:25:53 +00:00
6d667880e5 Documented changes and release timestamp 2009-01-04 11:37:05 +00:00
1a667c86bc Updated cdrskin tarball generator 2009-01-04 11:36:33 +00:00
7c64d4bc13 Made number transition to 0.6.1 2009-01-04 11:35:19 +00:00
6fea3d0a9b Updated copyright claims to year 2009 2009-01-04 11:29:37 +00:00
687bde257c Cosmetic changes 2008-12-29 10:53:58 +00:00
1de41908a8 Fixed denial of fast formatting with BD-RE introduced by revision 2280 2008-12-22 13:05:51 +00:00
8af33586e8 Clarified blank, appendable, closed burn_disc_status 2008-12-19 20:35:43 +00:00
3ea5106d68 Removed project overview and references to libisofs and libisoburn 2008-12-17 11:12:19 +00:00
0ca643d0a4 Removed project overview and references to libisofs and libisoburn 2008-12-17 09:34:53 +00:00
d50c90b7be New API function burn_get_read_capacity() 2008-12-17 09:19:34 +00:00
1b5ab0834e Updated cdrskin web page 2008-12-14 14:39:40 +00:00
147cb430d1 Updated libburner to BD-R 2008-12-14 10:45:04 +00:00
1cbe3afdcc Now producing libburn.so.4.24.0 2008-12-13 14:49:39 +00:00
817edbaeea Interpreting feature 0023h for BD-R formatting capabilities 2008-12-12 21:40:34 +00:00
6552c8267c Making format size of BD-RE and BD-R quite freely adjustable 2008-12-12 11:22:14 +00:00
82fcf62309 Catching BD-R zero spare formatting with NOTE rather than SORRY 2008-12-11 09:22:33 +00:00
c1572c271f Rejecting unformattable BD-R more early 2008-12-11 07:23:29 +00:00
83ed108298 Mentioning BD-R in documentation 2008-12-10 17:16:19 +00:00
0d669b4369 Formatting of BD-R SRM to default size and by index 2008-12-10 11:43:28 +00:00
22554efe4f Formatting of BD-R SRM to default size and by index 2008-12-10 09:26:09 +00:00
eb7e20a02c Beginning to implement write code for BD-R SRM without POW 2008-12-09 12:36:28 +00:00
a5e2729604 Beginning to implement write code for BD-R SRM without POW 2008-12-09 12:35:13 +00:00
d52ea49eb6 Documented changes and release timestamp 2008-12-07 16:04:38 +00:00
96e1cc451c Updated cdrskin tarball generator 2008-12-07 16:02:30 +00:00
bfba58b0fa 2008-12-07 16:00:45 +00:00
175061615e Defaulting sessions without leadout entry 2008-12-03 08:52:44 +00:00
717ad0f412 Circumventing BD-RE Quick Certification refusal of LG GGW-H20L YL03 2008-11-29 14:04:31 +00:00
f3ea35b9b8 Translating ASC=0x31 formatting error messages, reporting command names 2008-11-29 14:01:41 +00:00
bb9ef6b988 Changed error severity with TOC truncation to MISHAP 2008-11-27 17:21:54 +00:00
aa606552eb Truncating eventually detected damaged CD table-of-content 2008-11-27 08:11:03 +00:00
9d99e7874a Added tests against the SIGSEGV of ticket 146 2008-11-26 21:06:37 +00:00
d1483a15da Mentioned FreeBSD peculiarities in our docs 2008-11-21 21:45:23 +00:00
ed60d9a644 Removed remark that use of statvfs() was untested with FreeBSD 2008-11-15 22:07:24 +00:00
bd5d8e8991 Documented changes and release timestamp 2008-11-12 12:54:21 +00:00
bf64271c67 Updated cdrskin tarball generator 2008-11-12 12:52:22 +00:00
b0c8bbd48d Made number transition to 0.5.7 2008-11-12 12:51:07 +00:00
2fb19dd08e Avoiding warning message about implicitely declared burn_fifo_abort() 2008-11-12 07:53:01 +00:00
2ce3199241 Disabling the sigsegv provoking new debug message 2008-11-08 20:25:38 +00:00
6fe53827da Cancelling libburn fifo thread before freeing the fifo object 2008-11-08 14:18:14 +00:00
6053f3a6e3 Clarified behavior of burn_source with pipes 2008-11-08 13:48:59 +00:00
de274ddaff Bug fix: Unsuitable write modes were caught silently and later than desired 2008-11-01 12:13:26 +00:00
92b0e145d5 Fixed incomplete sentence in man cdrskin 2008-10-15 10:35:06 +00:00
4a5083739d A clarification in comment about burn_disc_format() 2008-10-15 10:33:09 +00:00
7a8040fe9f Documented changes and release timestamp 2008-10-05 12:45:10 +00:00
57df15054f Updated cdrskin tarball generator 2008-10-05 12:43:18 +00:00
a57cf121d8 Made number transition to next development cycle 2008-10-05 12:41:44 +00:00
935239b4f9 Incremented LT_CURRENT and LT_AGE to get libburn.so.4.18.0 2008-10-04 07:39:22 +00:00
e50cc04374 Mentioned new xorriso capabilities in man cdrskin 2008-10-04 07:29:28 +00:00
89c12404d0 Prevented SIGSEGV after illegal drive operations during sync write 2008-10-04 07:27:43 +00:00
78642d08ae Bug fix: /dev/sr0 was accepted as enumerable address on Linux 2.4 2008-09-29 07:35:30 +00:00
c2c2499862 Bug fix: Potential buffer overflow introduced with revision 2024 2008-09-28 19:39:00 +00:00
32252122b8 Mentioned recent releases of libisofs and libisoburn 2008-09-24 20:34:01 +00:00
63a48571af Corrected pacifier text (Ticket 141) 2008-09-16 06:04:08 +00:00
006fb98aee Gave up problematic and unused version.h 2008-09-14 17:45:11 +00:00
afded80e10 Hopefully made out-of-tree building possible 2008-09-12 19:51:19 +00:00
fb3d2de5df Described ISO 9660 multi-session on overwriteable media 2008-09-12 10:04:41 +00:00
c640c7954b Trying to avoid unnecessary access to sibling device objects 2008-09-09 13:20:08 +00:00
bc30c4201a Issueing many SCSI error messages in cleartext now 2008-08-30 10:44:45 +00:00
50b587a22c Mentioned release of libisoburn-0.2.4 2008-08-30 10:39:46 +00:00
cd99716ab5 Documented changes and release timestamp 2008-08-20 10:09:35 +00:00
13bdbd3555 Updated cdrskin tarball generator 2008-08-20 10:08:16 +00:00
711c055730 Made number transition to 0.5.3 2008-08-20 10:06:01 +00:00
83 changed files with 15700 additions and 1862 deletions

View File

@ -1,12 +1,12 @@
Derek Foreman <derek@signalmarketing.com> and Ben Jansens <xor@orodu.net>
Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
Mario Danic <mario.danic@gmail.com>, Thomas Schmitt <scdbackup@gmx.net>
Copyright (C) 2006-2008 Mario Danic, Thomas Schmitt
Copyright (C) 2006-2010 Mario Danic, Thomas Schmitt
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2 as
published by the Free Software Foundation.
it under the terms of the GNU General Public License version 2 or later
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of

View File

@ -1,4 +1,8 @@
pkgconfigdir=$(libdir)/pkgconfig
# ts A90315 : LIBBURNIA_PKGCONFDIR is defined OS specific in acinclude.m4
# was: pkgconfigdir=$(libdir)/pkgconfig
pkgconfigdir=$(LIBBURNIA_PKGCONFDIR)
libincludedir=$(includedir)/libburn
lib_LTLIBRARIES = libburn/libburn.la
@ -8,6 +12,9 @@ lib_LTLIBRARIES = libburn/libburn.la
# Build libraries
libburn_libburn_la_LDFLAGS = \
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
# This causes undesired .o names
# configure.ac appends -D options to variable CFLAG
### libburn_libburn_la_CFLAGS = $(LIBBURN_DVD_OBS_64K)
libburn_libburn_la_LIBADD = $(LIBBURN_ARCH_LIBS) $(THREAD_LIBS)
libburn_libburn_la_SOURCES = \
libburn/async.c \
@ -21,13 +28,13 @@ libburn_libburn_la_SOURCES = \
libburn/debug.h \
libburn/drive.c \
libburn/drive.h \
libburn/ecma130ab.c \
libburn/ecma130ab.h \
libburn/error.h \
libburn/file.c \
libburn/file.h \
libburn/init.c \
libburn/init.h \
libburn/lec.c \
libburn/lec.h \
libburn/libburn.h \
libburn/libdax_audioxtr.h \
libburn/libdax_audioxtr.c \
@ -82,32 +89,34 @@ noinst_PROGRAMS = \
bin_PROGRAMS = \
cdrskin/cdrskin
LIBBURN_EXTRALIBS = $(LIBBURN_ARCH_LIBS) $(THREAD_LIBS)
test_libburner_CPPFLAGS = -Ilibburn
test_libburner_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
test_libburner_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
test_libburner_SOURCES = test/libburner.c
test_telltoc_CPPFLAGS = -Ilibburn
test_telltoc_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
test_telltoc_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
test_telltoc_SOURCES = test/telltoc.c
test_dewav_CPPFLAGS = -Ilibburn
test_dewav_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
test_dewav_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
test_dewav_SOURCES = test/dewav.c
test_fake_au_CPPFLAGS =
test_fake_au_LDADD =
test_fake_au_SOURCES = test/fake_au.c
test_poll_CPPFLAGS = -Ilibburn
test_poll_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
test_poll_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
test_poll_SOURCES = test/poll.c
test_structest_CPPFLAGS = -Ilibburn
test_structest_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
test_structest_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
test_structest_SOURCES = test/structest.c
## cdrskin construction site - ts A60816 - A80716
## cdrskin construction site - ts A60816 - B00611
cdrskin_cdrskin_CPPFLAGS = -Ilibburn
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_0_5_1
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_0_8_2
# cdrskin_cdrskin_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
# cdrskin_cdrskin_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
# ts A80123, change proposed by Simon Huggins to cause dynamic libburn linking
cdrskin_cdrskin_LDADD = libburn/libburn.la $(THREAD_LIBS)
cdrskin_cdrskin_LDADD = libburn/libburn.la $(LIBBURN_EXTRALIBS)
cdrskin_cdrskin_SOURCES = cdrskin/cdrskin.c cdrskin/cdrfifo.c cdrskin/cdrfifo.h cdrskin/cdrskin_timestamp.h
##
@ -190,10 +199,16 @@ EXTRA_DIST = \
cdrskin/wiki_plain.txt \
cdrskin/cleanup.h \
cdrskin/cleanup.c \
libburn/os-dummy.h \
libburn/os-freebsd.h \
libburn/os-linux.h \
libburn/os-libcdio.h \
libburn/os-solaris.h \
libburn/sg-dummy.c \
libburn/sg-freebsd.c \
libburn/sg-linux.c \
libburn/sg-libcdio.c \
libburn/sg-solaris.c \
COPYING \
NEWS \
ChangeLog \

340
README
View File

@ -4,49 +4,84 @@
This all is under GPL.
(See GPL reference, our clarification and commitment at the end of this text)
------------------------------------------------------------------------------
libburnia-project.org
libburn-project.org
By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
Copyright (C) 2006-2008 Mario Danic, Thomas Schmitt
Still containing parts of
Libburn. By Derek Foreman <derek@signalmarketing.com> and
Ben Jansens <xor@orodu.net>
Copyright (C) 2006-2010 Mario Danic, Thomas Schmitt
Still containing parts of Libburn. By Derek Foreman <derek@signalmarketing.com>
and Ben Jansens <xor@orodu.net>
Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
These parts are to be replaced by own code of above libburnia-project.org
copyright holders and then libburnia-project.org is to be their sole copyright.
This is done to achieve the right to issue the clarification and the
commitment as written at the end of this text.
The rights and merits of the Libburn-copyright holders Derek Foreman and
Ben Jansens will be duely respected.
This libburnia-project.org toplevel README (C) 2006-2008 Thomas Schmitt
http://files.libburnia-project.org/releases/libburn-0.8.2.pl00.tar.gz
------------------------------------------------------------------------------
Build and Installation
Our build system is based on autotools. For preparing the build of a SVN
snapshot you will need autotools of at least version 1.7.
Check out from SVN by
svn co http://svn.libburnia-project.org/libburn/trunk libburn
go into directory libburn and apply autotools by
./bootstrap
From tarball
Alternatively you may unpack a release tarball for which you do not need
autotools installed.
Obtain libburn-0.8.2.pl00.tar.gz, take it to a directory of your choice and do:
To build a libburnia-project.org subproject it should be sufficient to go
into its toplevel directory (here: "libburn") and execute
tar xzf libburn-0.8.2.pl00.tar.gz
cd libburn-0.8.2
./configure --prefix=/usr
make
To make libburn accessible for running resp. application development,
and to install the cdrecord compatibility binary cdrskin, do:
and to install the cdrecord compatibility binary cdrskin, do
(as Superuser):
make install
This procedure installs libburn.so.4 and cdrskin depending on it.
For a standalone cdrskin binary, see cdrskin/README.
A behavioral conflict is known between any burn software and demons like hald
which probe CD drives. This can spoil burn runs for CD-R or CD-RW.
You may have to keep your hald away from the drive. See for example
http://www.freebsd.org/gnome/docs/halfaq.html
From SVN
Our build system is based on autotools. For preparing the build of a SVN
snapshot you will need autotools of at least version 1.7.
Do in a directory of your choice:
svn co http://svn.libburnia-project.org/libburn/trunk libburn-svn
cd libburn-svn
./bootstrap
./configure --prefix=/usr
make
make install
Warning: The trunk might contain experimental features which might not
persist until next release.
Special ./configure options
In some situations Linux may deliver a better write performance to drives if
the track input is read with O_DIRECT (see man 2 open). The API call
burn_os_open_track_src() and the input readers of cdrskin and libburn fifo
can be told to use this peculiar read mode by:
--enable-track-src-odirect
But often libburn call burn_write_opts_set_dvd_obs(opts, 64*1024) will yield
even better performance in such a situation. 64k can be made default at
configure time by:
--enable-dvd-obs-64k
This may be combined with above --enable-track-src-odirect .
Alternatively the transport of SCSI commands can be done via libcdio-0.83.
You may install it and re-run libburn's ./configure with option
--enable-libcdio
Make sure to re-compile all source files after running ./configure
make clean ; make
make install
Above procedure installs cdrskin depending on libburn.so.4 .
For a standalone cdrskin binary, see cdrskin/README.
------------------------------------------------------------------------------
An important part of the project, libisofs, is hosted in a bzr repository at
launchpad.net :
@ -57,7 +92,6 @@ Another part the project, libisoburn, is hosted in the libburnia SVN, too:
See README files there.
------------------------------------------------------------------------------
@ -65,24 +99,28 @@ See README files there.
libburnia-project.org is an open-source software project for reading, mastering
and writing optical discs.
For now this means only CD media and all single layer DVD media except DVD+R.
For now this means CD media, all DVD media except DVD-R DL, all BD media.
The project comprises of several more or less interdependent parts which
together strive to be a usable foundation for application development.
These are libraries, language bindings, and middleware binaries which emulate
classical (and valuable) Linux tools.
Currently it is supported on GNU/Linux with kernels >= 2.4,
on FreeBSD with ATAPI/CAM enabled in the kernel (see man atapicam),
and on OpenSolaris (tested with kernel 5.11).
On other X/Open compliant systems there will only be pseudo drives, but no
direct MMC operation on real CD/DVD/BD drives.
Our scope is currently Linux 2.4 and 2.6 only. For ports to other systems
we would need : login on a development machine resp. a live OS on CD or DVD,
advise from a system person about the equivalent of Linux sg or FreeBSD CAM,
volunteers for testing of realistic use cases.
For full ports to other systems we would need : login on a development machine
resp. a live OS on CD or DVD, advise from a system person about the equivalent
of Linux sg or FreeBSD CAM, volunteers for testing of realistic use cases.
We have a well tested code base for burning data and audio CDs and many DVD
types. The burn API is quite comprehensively documented and can be used to
build a presentable application.
We have a functional binary which emulates the core use cases of cdrecord in
order to prove that usability, and in order to allow you to explore libburn's
scope by help of existing cdrecord frontends.
We have a well tested code base for burning data and audio CDs, DVDs and BDs.
The burn API is quite comprehensively documented and can be used to build a
presentable application.
We have a functional application which emulates the core use cases of cdrecord
in order to prove that usability, and in order to allow you to explore
libburn's scope by help of existing cdrecord frontends.
ISO 9660 filesystems with Rock Ridge and Joliet extensions can be created
and manipulated quite freely. This capability together with our burn capability
@ -107,6 +145,8 @@ The project components (list subject to growth, hopefully):
also allows to grow ISO-9660 filesystem images on multi-session
media as well as on overwriteable media via the same API.
All media peculiarities are handled automatically.
It also contains the methods of command oriented application
xorriso and offers them via a C language API.
- cdrskin is a limited cdrecord compatibility wrapper for libburn.
cdrecord is a powerful GPL'ed burn program included in Joerg
@ -122,8 +162,12 @@ The project components (list subject to growth, hopefully):
- xorriso is an application of all three libraries which creates, loads,
manipulates and writes ISO 9660 filesystem images with
Rock Ridge extensions. Manipulation is not only adding or
overwriting of files but also deletion, renaming, and attribute
changing.
overwriting of files but also deleting, renaming, attribute
changing, incremental backups, activating boot images, and
extracting of files from ISO images to disk. An own ISO 9660
extension stores ACLs, xattr, and MD5 of file content.
All features of xorriso are also available via a C language API
of libisoburn.
See xorriso/README for more.
- "test" is a collection of application gestures and examples given by the
@ -142,10 +186,17 @@ any way and even may revoke such new features before the next release of
x.y.*[02468]. As soon as it is released, a feature is promised to persist.
SONAMES:
libburn.so.4 (since 0.3.4, March 2007),
libisofs.so.6 (since 0.6.2, February 2008),
libburn.so.4 (since 0.3.4, March 2007),
libisofs.so.6 (since 0.6.2, February 2008),
libisoburn.so.1 (since 0.1.0, February 2008).
Applications must use 64 bit off_t. E.g. by defining
#define _LARGEFILE_SOURCE
#define _FILE_OFFSET_BITS 64
or take special precautions to interface with the libraries by 64 bit integers
where the .h files prescribe off_t. To reduce libburn's off_t size to 32 bit
will keep it from processing tracks of more than 2 GB size.
------------------------------------------------------------------------------
Project history as far as known to me:
@ -173,7 +224,7 @@ Project history as far as known to me:
discontent.
The situation first caused me to publically regret it and then - after i
got the opportunity to move in with cdrskin - gave me true reason to
personally apologize to Derek Foreman, Ben Jansens and the contibutors at
personally apologize to Derek Foreman, Ben Jansens and the contributors at
icculus.org/burn. Posted to both projects:
http://lists.freedesktop.org/archives/libburn/2006-August/000446.html
http://mailman-mail1.webfaction.com/pipermail/libburn-hackers/2006-August/000024.html
@ -277,7 +328,7 @@ Project history as far as known to me:
image tree nodes. It now depends on libisofs-0.6.4 and libburn-0.4.4.
xorriso makes use of new libisofs features by performing incremental
updates of directory trees and by cutting oversized data files into
pieces. A primitive single session emulation of cdrcord and mkisofs is
pieces. A primitive single session emulation of cdrecord and mkisofs is
provided.
- 10th May 2008 libburn-0.4.6 supports formatting and writing of BD-RE,
@ -300,12 +351,188 @@ Project history as far as known to me:
- 16th Jul 2008 libburn-0.5.0 handles systems with no /dev/sr* but only
/dev/scd*.
- 19th Jul 2008 libisoburn/xorriso-0.2.2 can do multi-session in mkisofs
and cdrecord style. xorriso now can serve underneath growisofs.
- 20th Aug 2008 libburn-0.5.2 revokes the necessity that a drive must be
enumerable in order to be adressable. Enumeration is enhanced by examining
/proc/sys/dev/cdrom/info.
- 24th Aug 2008 libisoburn/xorriso-0.2.4 introduces a media readability check
with data retrieval option.
- 18th Sep 2008 libisofs-0.6.8 supports ISO 9660 Level 3 which allows very
large data files in the image.
- 20th Sep 2008 libisoburn/xorriso-0.2.6 takes into respect the new Level 3
capabilities of libisofs.
- 6th Oct 2008 libburn-0.5.4 adjusts the changes of 0.5.2 to the needs of
Linux kernel 2.4 and introduces human readable SCSI error messages.
- 6th Oct 2008 libisofs-0.6.10 fixes two bugs which prevented adding and
manipulation of ISOLINUX boot images.
- 15th Oct 2008 libisoburn/xorriso-0.2.8 can activate and maintain an
ISOLINUX boot image by an EL Torito boot record.
- 12th Nov 2008 libburn-0.5.6 fixes usage of freed memory by the fifo thread
of an aborted burn run.
- 26th Nov 2008 libisofs-0.6.12 can produce a ISOLINUX isohybrid MBR on the fly
and allows to produce ISO images which resemble old mkisofs images.
- 2nd Dec 2008 libisoburn-0.3.0. xorriso now is ready for exotic character
sets, for legacy FreeBSD systems which expect an outdated Rock Ridge
signature, and for producing ISO images with MBR which boot from hard disk
or USB stick. Three minor bugs were fixed.
- 7th Dec 2008 libburn-0.5.8 prevents a SIGSEGV with wierd CD table-of-content
and improves BD-RE formatting.
- 9th Dec 2008 Our project received a donation from Thomas Weber.
- 2nd Jan 2009 libburn-0.6.0 allows to format BD-R and to write to either
formatted or unformatted BD-R.
- 6th Jan 2009 libisoburn-0.3.2. xorriso can produce and execute commands for
mounting older sessions from all kinds of media. Pseudo-drives outside the
/dev/ tree can be addressed without prefix "stdio:".
- 20th Feb 2009 libburn-0.6.2 source release now compiles out of the box
on FreeBSD.
- 28 Feb 2009 libisofs-0.6.14 can record ACLs and Extended Attributes xattr
in its ISO images.
- 01 Mar 2009 libisoburn-0.3.4. xorriso makes use of the ACL and xattr
capabilities provided by libisofs for xorriso backup features.
- 11 Mar 2009 libisofs-0.6.16 of libisofs fixes two bugs which on Solaris
prevented to navigate the ISO images by ".." and to recognize the Rock Ridge
extensions of ISO images. The ban to build libisofs on operating systems
other than Linux and FreeBSD has been lifted.
- 13 Mar 2009 libburn-0.6.4 got a dummy adapter for SCSI/MMC command transport.
It will show no drives and thus libburn will only be able to perform
operations on "stdio:" pseudo drives. Nevertheless this allowed to lift the
ban to build libburn on operating systems other than Linux and FreeBSD.
- 16 Mar 2009 libisoburn-0.3.6: xorriso uses RRIP version 1.10 as default
in order to be mountable where mkisofs images are mountable.
- 17 Apr 2009 libisofs-0.6.18 introduces content filtering of data files.
Built-in filters allow compression to formats gzip and zisofs. External
filter processes allow arbitrary data conversions like encryption.
- 19 Apr 2009 libisoburn-0.3.8 makes use of the new libisofs capability to
perform content filtering of data files.
- 08 May 2009 libburn-0.6.6 fixes a bug with aborting on broken output pipe
and a bug with device scan on FreeBSD.
- 31 May 2009 libisofs-0.6.20 can record hard link relations in ISO images
and offers support with restoring them to disk. Current Linux kernels will
mount images with such hard links but will attribute a unique inode number
to each file.
- 28 Jun 2009 libisoburn-0.4.0: xorriso can record and restore hard link
relations of files. Performance of data reading has been improved. Option
-find now supports logical operators with its tests.
- 14 Jul 2009 libburn-0.6.8 fixes bugs and shortcommings with old MMC-1 drives
and with large SCSI bus numbers as handed out by Linux for USB drives.
- 20 Jul 2009 libisoburn-0.4.0.pl01 fixes a regression in xorriso which caused
data loss in older sessions if xorriso was used underneath growisofs.
Affected are releases since libisoburn-0.3.2 in january 2009.
- 25 Aug 2009 libisofs-0.6.22 can record MD5 checksums for the whole session
and for each single data file. Checksum tags allow to verify superblock and
directory tree before importing them.
- 27 Aug 2009 libburn-0.7.0 allows to calm down a drive and to inquire its
supported profiles. It works around some pitfalls with U3 enhanced memory
sticks which emulate a CD-ROM.
- 27 Aug 2009 libisoburn-0.4.0.pl00 can record MD5 checksums by which one may
verify the session or single data files in the image. When comparing image
files with files in the local filesystem, the MD5 sums avoid the need for
reading file content from the image.
- 22 Sep 2009 libisoburn-0.4.0.pl01 fixes a bug in xorriso option -cut_out.
- 08 Oct 2009 libisofs-0.6.24 fixes a bug which could cause the loss of blanks
in file names when a new session got added to an ISO image. With names
shorter than 251 characters this happened only to trailing blanks.
- 08 Oct 2009 libisoburn-0.4.0.pl02 fixes bugs with xorriso option -for_backup,
with xorrisofs -help, and with xorrecord -help.
- 12 Oct 2009 libburn-0.7.2 fixes a bug with CD TAO multi-track dummy sessions.
It can retrieve media product info and can process track input which was
prepared for CD-ROM XA Mode 2 Form 1. cdrskin now performs option -minfo.
- 28 Oct 2009 libisoburn-0.4.4 fixes a bug with cdrecord emulation and
introduces new information options about media type and ISO image id strings.
On Linux it helps with mounting two sessions of the same media
simultaneously.
- 12 Nov 2009 libburn-0.7.2.pl01 works around problems with Pioneer DVR-216D.
DVD-R runs made the drive stuck. Ejecting the tray did not work properly.
- 06 Dec 2009 libburn-0.7.4 works around problems with newer DVD burners,
provides throughput enhancements with hampered busses on Linux, and new
API calls to log SCSI commands and to control the libburn fifo.
- 09 Dec 2009 libisoburn-0.4.6 allows performance tuning of output to DVD
drives or disk files.
- 26 Dec 2009 libburn-0.7.4.pl01 fixes the release tarball which was lacking
the files of the generic system adapter for X/Open.
- 29 Dec 2009 Our project received a donation for purchasing a fine small
computer which shall serve as OS farm for development and support.
- 20 Jan 2010 Version 0.6.26 of libisofs fixes minor bugs and shall enhance
portability.
- 22 Jan 2010 libburn-0.7.6 has an improved system adapter for FreeBSD,
fixes bugs about the generic X/Open system adapter, and allows to use
libcdio >= 0.83 as SCSI transport facility.
- 10 Feb 2010 libisofs-0.6.28 fixes a regression about bootable images which
was introduced by version 0.6.22 in August 2009.
- 23 Feb 2010 libisoburn-0.5.0 marks the transition of the xorriso standalone
version to an official GNU project. The name changed to "GNU xorriso" and its
license is now GPLv3+.
The licenses of libburnia libraries and applications are not affected by
this change.
- 10 Mar 2010 libburn-0.7.8 fixes bugs and improves the built-in abort handler
on FreeBSD.
- 30 Mar 2010 Release 0.5.2 of libisoburn provides xorriso documentation in
GNU Texinfo format with embedded extra data to derive a full man page.
- 09 Apr 2010 libburn-0.8.0 now works with ahci driver on FreeBSD 8-STABLE.
- 03 May 2010 Version 0.6.32 of libisofs is able to create ISO images with
multiple boot images. All boot catalog parameters described in El-Torito
specs can be set and inquired. This allows to use GRUB boot images for EFI.
- 04 May 2010 Release 0.5.6.pl00 of libisoburn makes use of the new libisofs
capabilities about boot images.
- 11 Jun 2010 libburn-0.8.2 now works on Solaris.
------------------------------------------------------------------------------
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
the Free Software Foundation. To be exact: version 2 of that License.
it under the terms of the GNU General Public License version 2 or later
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@ -323,16 +550,16 @@ other copyrighted code has been replaced by ours and by copyright-free
contributions of our friends:
------------------------------------------------------------------------------
We, the copyright holders, agree on the interpretation that
dynamical linking of our libraries constitutes "use of" and
not "derivation from" our work in the sense of GPL, provided
those libraries are compiled from our unaltered code.
We, the copyright holders, agree on the interpretation that dynamical linking
of our libraries constitutes "use of" and not "derivation from" our work in
the sense of GPL, provided those libraries are compiled from our unaltered
code or from altered code published under GPL.
Thus you may link our libraries dynamically with applications
which are not under GPL. You may distribute our libraries and
application tools in binary form, if you fulfill the usual
condition of GPL to offer a copy of the source code -altered
or unaltered- under GPL.
So we will not raise legal protest if you link our libraries dynamically with
applications which are not under GPL, or if you distribute our libraries
and application tools in binary form, as long as you fulfill the usual
condition of GPL to offer a copy of their source code -altered or unaltered-
under GPL.
We ask you politely to use our work in open source spirit
and with the due reference to the entire open source community.
@ -349,4 +576,5 @@ means to qualify for GPL.
For now we are firmly committed to maintain one single license: GPL.
signed: Mario Danic, Thomas Schmitt
Agreement joined later by: Vreixo Formoso

View File

@ -1,22 +1,94 @@
AC_DEFUN([LIBBURNIA_SET_FLAGS],
[
case $target_os in
freebsd*)
LDFLAGS="$LDFLAGS -L/usr/local/lib"
CPPFLAGS="$CPPFLAGS -I/usr/local/include"
;;
esac
])
AC_DEFUN([TARGET_SHIZZLE],
[
ARCH=""
LIBBURNIA_PKGCONFDIR="$libdir"/pkgconfig
AC_MSG_CHECKING([target operating system])
case $target in
*-*-linux*)
case $target_os in
linux*)
ARCH=linux
LIBBURN_ARCH_LIBS=
;;
*-*-freebsd*)
freebsd*)
ARCH=freebsd
LIBBURN_ARCH_LIBS=-lcam
LIBBURNIA_PKGCONFDIR=$(echo "$libdir" | sed 's/\/lib$/\/libdata/')/pkgconfig
;;
kfreebsd*-gnu)
ARCH=freebsd
LIBBURN_ARCH_LIBS=-lcam
;;
*)
AC_ERROR([You are attempting to compile for an unsupported platform])
ARCH=
LIBBURN_ARCH_LIBS=
# AC_ERROR([You are attempting to compile for an unsupported platform])
;;
esac
AC_MSG_RESULT([$ARCH])
])
dnl LIBBURNIA_SET_PKGCONFIG determines the install directory for the *.pc file.
dnl Important: Must be performed _after_ TARGET_SHIZZLE
dnl
AC_DEFUN([LIBBURNIA_SET_PKGCONFIG],
[
### for testing --enable-libdir-pkgconfig on Linux
### LIBBURNIA_PKGCONFDIR="$libdir"data/pkgconfig
if test "x$LIBBURNIA_PKGCONFDIR" = "x$libdir"/pkgconfig
then
dummy=dummy
else
AC_ARG_ENABLE(libdir-pkgconfig,
[ --enable-libdir-pkgconfig Install to $libdir/pkgconfig on any OS, default=no],
, enable_libdir_pkgconfig="no")
AC_MSG_CHECKING([for --enable-libdir-pkgconfig])
if test "x$enable_libdir_pkgconfig" = xyes
then
LIBBURNIA_PKGCONFDIR="$libdir"/pkgconfig
fi
AC_MSG_RESULT([$enable_libdir_pkgconfig])
fi
libburnia_pkgconfig_override="no"
AC_ARG_ENABLE(pkgconfig-path,
[ --enable-pkgconfig-path=DIR Absolute path of directory for libisofs-*.pc],
libburnia_pkgconfig_override="yes" , enable_pkgconfig_path="none")
AC_MSG_CHECKING([for overridden pkgconfig directory path])
if test "x$enable_pkgconfig_path" = xno
then
libburnia_pkgconfig_override="no"
fi
if test "x$enable_pkgconfig_path" = x -o "x$enable_pkgconfig_path" = xyes
then
libburnia_pkgconfig_override="invalid argument"
fi
if test "x$libburnia_pkgconfig_override" = xyes
then
LIBBURNIA_PKGCONFDIR="$enable_pkgconfig_path"
AC_MSG_RESULT([$LIBBURNIA_PKGCONFDIR])
else
AC_MSG_RESULT([$libburnia_pkgconfig_override])
fi
AC_SUBST(LIBBURNIA_PKGCONFDIR)
dnl For debugging only
### AC_MSG_RESULT([LIBBURNIA_PKGCONFDIR = $LIBBURNIA_PKGCONFDIR])
])

View File

@ -4,15 +4,21 @@
cdrskin. By Thomas Schmitt <scdbackup@gmx.net>
Integrated sub project of libburnia-project.org but also published via:
http://scdbackup.sourceforge.net/cdrskin_eng.html
http://scdbackup.sourceforge.net/cdrskin-0.5.1.tar.gz
Copyright (C) 2006-2008 Thomas Schmitt, provided under GPL version 2.
http://scdbackup.sourceforge.net/cdrskin-0.8.2.pl00.tar.gz
Copyright (C) 2006-2010 Thomas Schmitt, provided under GPL version 2 or later.
------------------------------------------------------------------------------
cdrskin is a limited cdrecord compatibility wrapper which allows to use
most of the libburn features from the command line.
Currently it is only supported on Linux with kernels >= 2.4.
Currently it is supported on GNU/Linux with kernels >= 2.4,
on FreeBSD and on OpenSolaris.
IDE drives under Linux 2.4. need kernel module ide-scsi.
ATA and SATA drives under FreeBSD need kernel module atapicam.
On other X/Open compliant systems there will only be emulated drives, but no
direct MMC operation on real CD/DVD/BD drives.
By using this software you agree to the disclaimer at the end of this text
"This software is provided as is. There is no warranty implied and ..."
@ -20,10 +26,10 @@ By using this software you agree to the disclaimer at the end of this text
Compilation, First Glimpse, Installation
Obtain cdrskin-0.5.1.tar.gz, take it to a directory of your choice and do:
Obtain cdrskin-0.8.2.pl00.tar.gz, take it to a directory of your choice and do:
tar xzf cdrskin-0.5.1.tar.gz
cd cdrskin-0.5.1
tar xzf cdrskin-0.8.2.pl00.tar.gz
cd cdrskin-0.8.2
Within that directory execute:
@ -31,8 +37,7 @@ Within that directory execute:
make
This will already produce a cdrskin binary. But it will be necessary to
install libburn in order to use this binary. Installation of libburn is
beyond the scope of cdrskin. For this, see included libburn docs.
install libburn in order to use this binary.
In order to surely get a standalone binary, execute
@ -69,7 +74,7 @@ It is not necessary for the standalone cdrskin binary to have libburn
installed, since it incorporates the necessary libburn parts at compile time.
It will not collide with an installed version of libburn either.
But libpthread must be installed on the system and glibc has to match. (See
below for a way to create a statically linked binary.)
below for a way to create a totally static linked binary.)
To install the man page, you may do: echo $MANPATH and choose one of the
listed directories to copy the man-page under its ./man1 directory. Like:
@ -99,17 +104,25 @@ The output of cdrskin --devices might look like
0 dev='/dev/sr0' rwrwr- : '_NEC' 'DVD_RW ND-4570A'
1 dev='/dev/sr1' rwrw-- : 'HL-DT-ST' 'DVDRAM GSA-4082B'
So full and insecure enabling of both for everybody would look like
chmod a+rw /dev/sr0 /dev/sr1
On Linux, full and insecure enabling of both for everybody would look like
chmod a+rw /dev/sr0 /dev/hda
This is equivalent to the traditional setup chmod a+x,u+s cdrecord.
On FreeBSD, device permissions are to be set in /etc/devfs.rules.
On Solaris, pfexec privileges may be restricted to "basic,sys_devices".
See below "System Dependend Drive Permission Examples".
I strongly discourage to run cdrskin with setuid root or via sudo !
It is not checked for the necessary degree of hacker safety.
Better consider to grant the necessary permissions to group "floppy"
and to add users to it.
A behavioral conflict is known between any burn software and demons like hald
which probe CD drives. This can spoil burn runs for CD-R or CD-RW.
You may have to keep your hald away from the drive. See for example
http://www.freebsd.org/gnome/docs/halfaq.html
Consider to put all authorized users into group "floppy", to chgrp the
device file to that group and to disallow w-access to others.
Helpful with Linux kernel 2.4 is a special SCSI feature:
It is possible to address a scsi(-emulated) drive via associated device files
@ -137,7 +150,7 @@ Obtain some info about the drive
cdrskin dev=0,1,0 -checkdrive
Obtain some info about the drive and the inserted media
cdrskin dev=0,1,0 -atip -v
cdrskin dev=0,1,0 -atip -v -minfo
Prepare CD-RW or DVD-RW for re-use, DVD-RAM or BD-RE for first use
cdrskin -v dev=/dev/sg1 blank=as_needed -eject
@ -273,13 +286,16 @@ behavior.
BD-RE media need formatting before first use. cdrskin option "blank=as_needed"
recognizes unformatted BD-RE and applies a lengthy formatting run.
During write operations DVD-RAM and BD-RE automatically apply defect
management. This usually slows them down to half nominal speed. If drive
During write operations DVD-RAM and BD-RE automatically apply Defect
Management. This usually slows them down to half nominal speed. If drive
and media produce flawless results anyway, then one can try to reach full
nominal speed by option "stream_recording=on".
In this case bad blocks are not detected during write and not even previously
known bad blocks are avoided. So you have to make your own readability tests
and go back to half speed as soon as the first read errors show up.
Instead of "on" one may also set a start address for stream recording.
Like "stream_recording=100m". This will write slowly to the first 100 MB of
the media and accelerate when writing to higher addresses.
Option --grow_overwriteable_iso allows -multi (although unneeded), enables
-msinfo and -toc, and makes blank=fast an invalidator for ISO filesystems
@ -349,14 +365,24 @@ Incremental Streaming afterwards. So blank=fast will do full blanking.
blank=deformat_sequential_quickest is faster but might yield DAO-only media.
DVD+R and DVD+R DL
DVD+R , DVD+R DL , BD-R
From the view of cdrskin they behave much like DVD-R. Each track gets wrapped
into an own session, though.
DVD+R DL appear as extra large DVD+R. cdrskin does not allow to set the address
of the layer break where a reading drive might show some delay while switching
between both media layers.
BD-R are sold unformatted blank. If used without initial formatting then the
drive is supposed to format them to maximum payload size with no Defect
Management (see also above with BD-RE).
If Defect Management is desired then BD-R need to be formatted before the
first attempt to write a session to them.
blank=format_if_needed will detect the situation and eventually apply
default sized Defect Management formatting.
blank=format_defectmgt_* will apply non-default parameters to formatting.
Emulated Drives
@ -376,6 +402,26 @@ drive. See man page section FILES for a way to lift that ban.
Special compilation variations
All following options of ./configure and cdrskin/compile_cdrskin.sh are
combinable. After runs of ./configure do as next:
make clean ; make
In some situations Linux may deliver a better write performance to drives if
the track input is read with O_DIRECT (see man 2 open). The API call
burn_os_open_track_src() and the input readers of cdrskin and libburn fifo
can be told to use this peculiar read mode by:
--enable-track-src-odirect
But often cdrskin option dvd_obs=64k will yield even better performance in
such a situation. 64k can be made default at compile time by
cdrskin/compile_cdrskin.sh -dvd_obs_64k
It can also be enabled at configure time by
./configure ... --enable-dvd-obs-64k ...
Alternatively the transport of SCSI commands can be done via libcdio-0.83.
You may install it and re-run libburn's ./configure with option
--enable-libcdio
You may get a (super fat) statically linked binary by :
cdrskin/compile_cdrskin.sh -static
if your system supports static linking, at all. This will not help with kernels
@ -391,6 +437,84 @@ It will not read startup files, will abort on option dev_translation= ,
will not have a fifo buffer, and will not be able to put out help texts or
debugging messages.
------------------------------------------------------------------------------
System Dependend Drive Permission Examples
Accessing the optical drives requires privileges which usually are granted
only to the superuser. Linux, FreeBSD and Solaris offer quite different
approaches for avoiding the need for unrestricted privileges.
First check whether some friendly system setting already allows you to
access the drives as normal user:
cdrskin --devices
Those drives of which you see address and type strings are already usable.
If there remain drives invisible which the superuser can see by the same
command, then the following examples might help:
---------------------
On all three systems:
---------------------
Add the authorized users of CD drives to group "floppy" in /etc/group.
If missing: create this group.
Changes to /etc/group often only affect new login sessions. So log out and in
before making the first tests.
---------
On Linux:
---------
Allow rw-access to the drives
chgrp floppy /dev/sr0 /dev/sr1
chmod g+rw /dev/sr0 /dev/sr1
It might be necessary to perform chgrp and chmod after each reboot or to
edit distro dependent device configuration files for permanent settings.
-----------
On FreeBSD:
-----------
Edit /etc/devfs.rules and make sure to have these lines
[localrules=10]
add path 'acd*' mode 0664 group floppy
add path 'cd*' mode 0664 group floppy
add path 'pass*' mode 0664 group floppy
add path 'xpt*' mode 0664 group floppy
[localrules=5]
add path 'pass*' mode 0664 group floppy
add path 'cd*' mode 0664 group floppy
add path 'xpt*' mode 0664 group floppy
add path 'acd*' mode 0664 group floppy
Edit /etc/rc.conf and add the following line if missing
devfs_system_ruleset="localrules"
This gets into effect by reboot or by command
/etc/rc.d/devfs start
-----------
On Solaris:
-----------
Run cdrskin by
pfexec cdrskin ...arguments...
The following settings will make pfexec keep original UID and EUID and prevent
most superuser powers. Be aware that you still can manipulate all device files
if you have the file permissions for that.
Full root privileges for cdrskin can then be aquired only by command su.
Edit /etc/security/exec_attr and add this line to the other "Media Backup"
lines:
Media Backup:solaris:cmd:::/usr/local/bin/cdrskin:privs=basic,sys_devices
Edit /etc/user_attr and add profile "Media Backup" to the user's line:
thomas::::profiles=Media Backup,Primary Administrator;roles=root
See also man privileges, man exec_attr, man user_attr.
Then allow the group r-access to the drives
pfexec chgrp floppy /dev/rdsk/c3t0d0s2 /dev/rdsk/c4t0d0s2
pfexec chmod g+r /dev/rdsk/c3t0d0s2 /dev/rdsk/c4t0d0s2
The last two commands have to be executed after each boot. I do not know
the relevant device configuration files yet.
------------------------------------------------------------------------------
Project aspects and legal stuff
@ -407,7 +531,7 @@ are the cause. Any mistake of the burn program is supposed to be caught
by the drive's firmware and to lead to mere misburns.
The worst mishaps which hit the author imposed the need to reboot the
system because of drives gnawing endlessly on ill media. Permanent hardware
damage did not occur in 2.5 years of development. But one never knows ...
damage did not occur in 3.5 years of development. But one never knows ...
------------------------------------------------------------------------------
@ -419,7 +543,7 @@ contributions in a due way.
------------------------------------------------------------------------------
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License version 2
it under the terms of the GNU General Public License version 2 or later
as published by the Free Software Foundation.
This program is distributed in the hope that it will be useful,
@ -435,7 +559,7 @@ contributions in a due way.
Based on and sub project of:
libburnia-project.org
By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
Copyright (C) 2006-2008 Mario Danic, Thomas Schmitt
Copyright (C) 2006-2010 Mario Danic, Thomas Schmitt
libburnia-project.org is inspired by and in other components still containing
parts of
@ -446,34 +570,3 @@ See toplevel README for an overview of the current copyright situation in
libburnia-project.org.
------------------------------------------------------------------------------
cdrskin is currently copyright Thomas Schmitt only.
It adopts the following commitment by the toplevel copyright holders:
------------------------------------------------------------------------------
We, the copyright holders, agree on the interpretation that
dynamical linking of our libraries constitutes "use of" and
not "derivation from" our work in the sense of GPL, provided
those libraries are compiled from our unaltered code.
Thus you may link our libraries dynamically with applications
which are not under GPL. You may distribute our libraries and
application tools in binary form, if you fulfill the usual
condition of GPL to offer a copy of the source code -altered
or unaltered- under GPL.
We ask you politely to use our work in open source spirit
and with the due reference to the entire open source community.
If there should really arise the case where above clarification
does not suffice to fulfill a clear and neat request in open source
spirit that would otherwise be declined for mere formal reasons,
only in that case we will duely consider to issue a special license
covering only that special case.
It is the open source idea of responsible freedom which will be
decisive and you will have to prove that you exhausted all own
means to qualify for GPL.
For now we are firmly committed to maintain one single license: GPL.
signed for cdrskin: Thomas Schmitt

View File

@ -38,7 +38,7 @@ original="./libburn_svn_release.tgz"
# My changes are in $changes , mainly in $changes/cdrskin
changes="./libburn-release"
skin_release="0.5.0"
skin_release="0.8.2"
patch_level=".pl00"
skin_rev="$skin_release""$patch_level"
@ -117,6 +117,7 @@ cp -a "$cdrskin_dir" "$cdrskin_target"
# Remove copied vim.swp and binaries
rm "$cdrskin_target"/.*.swp
rm "$cdrskin_target"/.*.swo
rm "$cdrskin_target"/*.o
rm "$cdrskin_target"/cdrfifo
rm "$cdrskin_target"/cdrskin

View File

@ -38,7 +38,7 @@ original="./libburn_svn.tgz"
# My changes are in $changes , mainly in $changes/cdrskin
changes="./libburn-develop"
skin_release="0.5.1"
skin_release="0.8.3"
patch_level=""
skin_rev="$skin_release""$patch_level"
@ -116,6 +116,7 @@ cp -a "$cdrskin_dir" "$cdrskin_target"
# Remove copied vim.swp and binaries
rm "$cdrskin_target"/.*.swp
rm "$cdrskin_target"/.*.swo
rm "$cdrskin_target"/*.o
rm "$cdrskin_target"/cdrfifo
rm "$cdrskin_target"/cdrskin

View File

@ -25,6 +25,11 @@
#include <sys/time.h>
#include <sys/select.h>
#ifndef Cdrfifo_standalonE
/* <<< until release of 0.7.4 : for Libburn_has_open_trac_srC */
#include "../libburn/libburn.h"
#endif
#include "cdrfifo.h"
@ -120,7 +125,7 @@ struct CdrfifO {
struct burn_source object.
@param chunk_size Size of buffer block for a single transaction (0=default)
@param buffer_size Size of fifo buffer
@param flag Unused yet
@param flag bit0= Debugging verbosity
@return 1 on success, <=0 on failure
*/
int Cdrfifo_new(struct CdrfifO **ff, int source_fd, int dest_fd,
@ -174,7 +179,13 @@ int Cdrfifo_new(struct CdrfifO **ff, int source_fd, int dest_fd,
o->follow_up_fd_idx= -1;
o->next= o->prev= NULL;
o->chain_idx= 0;
#ifdef Libburn_has_open_trac_srC
o->buffer= burn_os_alloc_buffer((size_t) buffer_size, 0);
#else
o->buffer= TSOB_FELD(char,buffer_size);
#endif /* ! Libburn_has_open_trac_srC */
if(o->buffer==NULL)
goto failed;
return(1);
@ -192,10 +203,11 @@ int Cdrfifo_close(struct CdrfifO *o, int flag)
if(o->dest_fd!=-1)
close(o->dest_fd);
o->dest_fd= -1;
for(i=0; i<o->follow_up_fd_counter; i++)
for(i=0; i<o->follow_up_fd_counter; i++) {
if(o->follow_up_fds[i][1]!=-1)
close(o->follow_up_fds[i][1]);
o->follow_up_fds[i][1]= -1;
}
return(1);
}
@ -226,8 +238,14 @@ int Cdrfifo_destroy(struct CdrfifO **ff, int flag)
if(o->iso_fs_descr!=NULL)
free((char *) o->iso_fs_descr);
if(o->buffer!=NULL)
#ifdef Libburn_has_open_trac_srC
burn_os_free_buffer(o->buffer, o->buffer_size, 0);
#else
free((char *) o->buffer);
#endif /* Libburn_has_open_trac_srC */
free((char *) o);
(*ff)= NULL;
return(1);
@ -616,7 +634,7 @@ return: <0 = error , 0 = idle , 1 = did some work
*/
{
double buffer_space;
int can_read,can_write,ret,did_work= 0,idx,sod,eop_is_near,eop_idx;
int can_read,can_write= 0,ret,did_work= 0,idx,sod,eop_is_near,eop_idx;
buffer_space= Cdrfifo_tell_buffer_space(o,0);
if(o->dest_fd>=0) if(FD_ISSET((o->dest_fd),wts)) {
@ -659,6 +677,46 @@ return: <0 = error , 0 = idle , 1 = did some work
after_write:;
if(o->source_fd>=0) if(FD_ISSET((o->source_fd),rds)) {
can_read= o->buffer_size - o->write_idx;
#ifdef Libburn_has_open_trac_srC
/* ts A91115
This chunksize must be aligned to filesystem blocksize.
*/
#define Cdrfifo_o_direct_chunK 32768
if(o->write_idx < o->read_idx && o->write_idx + can_read > o->read_idx)
can_read= o->read_idx - o->write_idx;
if(o->fd_in_limit>=0.0)
if(can_read > o->fd_in_limit - o->fd_in_counter)
can_read= o->fd_in_limit - o->fd_in_counter;
/* Make sure to read with properly aligned size */
if(can_read > Cdrfifo_o_direct_chunK)
can_read= Cdrfifo_o_direct_chunK;
else if(can_read < Cdrfifo_o_direct_chunK)
can_read= -1;
ret= 0;
if(can_read>0)
ret= read(o->source_fd,o->buffer+o->write_idx,can_read);
if(can_read < 0) {
/* waiting for a full Cdrfifo_o_direct_chunK to fit */
if(can_write <= 0 && o->dest_fd >= 0) {
fd_set rds,wts,exs;
struct timeval wt;
FD_ZERO(&rds);
FD_ZERO(&wts);
FD_ZERO(&exs);
FD_SET((o->dest_fd),&wts);
wt.tv_sec= 0;
wt.tv_usec= 10000;
select(o->dest_fd + 1,&rds, &wts, &exs, &wt);
}
} else
#else /* Libburn_has_open_trac_srC */
if(can_read>o->chunk_size)
can_read= o->chunk_size;
if(o->write_idx<o->read_idx && o->write_idx+can_read > o->read_idx)
@ -669,6 +727,9 @@ after_write:;
ret= 0;
if(can_read>0)
ret= read(o->source_fd,o->buffer+o->write_idx,can_read);
#endif /* ! Libburn_has_open_trac_srC */
if(ret==-1) {
/* >>> handle input error */;

View File

@ -33,7 +33,7 @@ struct CdrfifO;
struct burn_source object.
@param chunk_size Size of buffer block for a single transaction (0=default)
@param buffer_size Size of fifo buffer
@param flag unused yet
@param flag bit0= Debugging verbosity
@return 1 on success, <=0 on failure
*/
int Cdrfifo_new(struct CdrfifO **ff, int source_fd, int dest_fd,

View File

@ -2,7 +2,7 @@
.\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1)
.TH CDRSKIN 1 "Aug 05, 2008"
.TH CDRSKIN 1 "Jun 10, 2010"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
@ -16,7 +16,7 @@
.\" .sp <n> insert n+1 empty lines
.\" for manpage-specific macros, see man(7)
.SH NAME
cdrskin \- burns preformatted data to CD, DVD, and BD-RE via libburn.
cdrskin \- burns preformatted data to CD, DVD, and BD via libburn.
.SH SYNOPSIS
.B cdrskin
.RI [ options | track_source_addresses ]
@ -28,14 +28,14 @@ cdrskin \- burns preformatted data to CD, DVD, and BD-RE via libburn.
.\" respectively.
.PP
\fBcdrskin\fP is a program that provides some of cdrecord's options
in a compatible way for CD media. With DVD and BD-RE it has its own ways.
in a compatible way for CD media. With DVD and BD it has its own ways.
You do not need to be superuser for its daily usage.
.SS
.B Overview of features:
.br
Blanking of CD-RW and DVD-RW.
.br
Formatting of DVD-RW, DVD+RW, DVD-RAM, BD-RE.
Formatting of DVD-RW, DVD+RW, DVD-RAM, BD.
.br
Burning of data or audio tracks to CD,
.br
@ -45,7 +45,7 @@ or in Session at Once mode for seamless tracks.
.br
Multi session on CD (follow-up sessions in TAO only)
.br
or on DVD-R[W] (in Incremental mode) or on DVD+R[/DL].
or on DVD-R[W] (in Incremental mode) or DVD+R[/DL] or BD-R.
.br
Single session on DVD-RW or DVD-R (Disk-at-once).
.br
@ -67,7 +67,7 @@ Write mode selection
.br
Recordable CD Media
.br
Sequentially Recordable DVD Media
Sequentially Recordable DVD or BD Media
.br
Overwriteable DVD or BD Media
.br
@ -82,7 +82,7 @@ A \fBtrack\fP stores a stream of bytes.
.br
Each track is initiated by one track source address argument, which may either
be "-" for standard input or the address of a readable file. If no write mode
is given explicitely then one will be chosen which matches the peculiarities
is given explicitly then one will be chosen which matches the peculiarities
of track sources and the state of the output media.
.PP
More than one track can be burned by a single run of cdrskin.
@ -93,13 +93,13 @@ Some media types can be kept appendable so that further tracks can
be written to them in subsequent runs of cdrskin (see option -multi).
Info about the addresses of burned tracks is kept in a table of
content (TOC) on media and can be retrieved via cdrskin option -toc.
These informations are also used by the operating systems' CD-ROM read drivers.
This information is also used by the operating systems' CD-ROM read drivers.
.PP
In general there are two types of tracks: data and audio. They differ in
sector size, throughput and readability via the systems' CD-ROM drivers
resp. by music CD players. With DVD and BD there is only type data.
.br
If not explicitely option -audio is given, then any track is burned as type
If not explicitly option -audio is given, then any track is burned as type
data, unless the track source is a file with suffix ".wav" or ".au" and has a
header part which identifies it as MS-WAVE resp. SUN Audio with suitable
parameters. Such files are burned as audio tracks by default.
@ -108,8 +108,9 @@ While audio tracks just contain a given time span of acoustic vibrations,
data tracks may have an arbitray meaning. Nevertheless, ISO-9660 filesystems
are established as a format which can represent a tree of directories and
files on all major operating systems. Such filesystem images can be
produced by programs mkisofs or genisoimage. They can also be extended by
follow-up tracks if prepared properly. See the man pages of said programs.
produced by programs mkisofs or genisoimage or xorriso.
They can also be extended by follow-up tracks if prepared properly.
See the man pages of said programs.
cdrskin is able to fulfill the needs about their option -C.
.br
Another type of data track content are archive formats which originally
@ -137,7 +138,7 @@ try to choose a write mode which matches the defined recording job,
the capabilities of the drive and the state of the present media.
.br
So the mentioning of write modes in the following paragraphs and in the
examples is not so much a demand that the user shall choose one explicitely,
examples is not so much a demand that the user shall choose one explicitly,
but rather an illustration of what to expect with particular media types.
.SS
.B Recordable CD Media:
@ -160,14 +161,16 @@ round of overwriting. Usually
is the appropriate option.
Blanking damages the previous content but does not
make it completely unreadable. It is no effective privacy precaution.
Multiple cycles of blanking and overwriting with random numbers might be.
Multiple cycles of blanking and overwriting with random numbers might be
needed.
.SS
.B Sequentially Recordable DVD Media:
.B Sequentially Recordable DVD or BD Media:
.br
Currently DVD-RW, DVD-R and DVD+R[/DL] can be used for the Sequential recording
model.
Currently DVD-RW, DVD-R , DVD+R[/DL], and BD-R can be used for the Sequential
recording model. It resembles the model of CD media. Only DVD-RW can be
blanked and re-used from scratch.
.br
This applies to DVD-RW only if they are in state "Sequential Recording".
DVD-RW are sequential media if they are in state "Sequential Recording".
The media must be either blank or appendable.
Newly purchased DVD-RW and DVD-R media are in this state.
Used DVD-RW get into blank sequential state by option
@ -178,20 +181,20 @@ With DVD-R[W] two write modes may be available:
Mode DAO has many restrictions. It does not work with
appendable media, allows no -multi and only a single track. The size of the
track needs to be known in advance. So either its source has to be a disk file
of recognizable size or the size has to be announced explicitely by options
of recognizable size or the size has to be announced explicitly by options
.B tsize=
or
.B tao_to_sao_tsize= .
.br
DAO is the only mode for media which do not offer feature 21h Incremental
Streaming. DAO may also be selected explicitely by option
Streaming. DAO may also be selected explicitly by option
.B -sao .
Program growisofs uses DAO on sequential DVD-R[W] media for maximum
DVD-ROM/-Video compatibility.
.br
The other mode, Incremental Streaming, is the default write mode if
it is available and if the restrictions of DAO would prevent the job.
Incremental Streaming may be selected explicitely by option
Incremental Streaming may be selected explicitly by option
.B -tao
as it resembles much CD TAO by allowing track sources of
unpredicted length and to keep media appendable by option
@ -199,14 +202,18 @@ unpredicted length and to keep media appendable by option
The only restriction towards CD-R[W] is the lack of support for -audio tracks.
Multiple tracks per session are permissible.
.br
The write modes for DVD+R[/DL] resemble those with DVD-R except that with +R
each track gets wrapped in an own session. There is no -dummy writing with
DVD+R[/DL].
The write modes for DVD+R[/DL] and BD-R resemble those with DVD-R except that
each track gets wrapped in an own session. There is no -dummy writing
with DVD+R[/DL] or BD-R.
.br
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
allows appendable media.
.br
BD-R may be formatted before first use to enable the Defect Management which
might catch and repair some bad spots at the expense of slow speed
even with flawless media.
.br
.B Note:
Option -multi might make DVD media unreadable in some DVD-ROM drives.
Best reader compatibility is achieved without it
@ -218,7 +225,7 @@ Currently types DVD+RW, DVD-RW, DVD-RAM and BD-RE can be overwritten via
cdrskin.
.br
Option -audio is not allowed. Only one track is allowed.
Option -multi cannot mark a recognizeable end of overwriteable media.
Option -multi cannot mark a recognizable end of overwriteable media.
Therefore -multi is banned unless ISO-9660 images shall be expandable by help
of option
.B --grow_overwriteable_iso .
@ -247,7 +254,7 @@ that it has to be formatted again. If in doubt, just give it a try.
.SS
.B Drive preparation and addressing:
.br
The drives, either CD burners or DVD burners, are accessed via addresses which
The drives, CD, DVD, or BD burners, are accessed via addresses which
are specific to libburn and the operating system. Those addresses get listed
by a run of \fBcdrskin --devices\fP.
.br
@ -264,19 +271,22 @@ the drive is somewhat higher but the overall system is much less at stake.
Consider to restrict rw-access to a single group which bundles the users who
are allowed to use the burner drive (like group "floppy").
.br
For drive permission examples on Linux, FreeBSD, and Solaris,
see cdrskin/README.
.br
.PP
If you only got one CD capable drive then you may leave out cdrskin option
\fBdev=\fP. Else you should use this option to address the drive you want.
.br
cdrskin option dev= not only accepts the listed addresses but also
traditional cdrecord SCSI addresses which on Linux consist of three
numbers: Bus,Target,Lun. There is also a related address family "ATA" which
traditional cdrecord SCSI addresses which consist of three numbers:
Bus,Target,Lun. On Linux there is also a related address family "ATA" which
accesses IDE drives not under control of Linux SCSI drivers:
ATA:Bus,Target,Lun.
.br
See option -scanbus for getting a list of cdrecord style addresses.
.br
Further are accepted on Linux: links to libburn-suitable device files,
Further are accepted: links to libburn-suitable device files,
device files which have the same major and minor device number,
and device files which have the same SCSI address parameters (e.g. /dev/sg0).
.br
@ -343,7 +353,7 @@ print "Mounted Media:" and media type text.
Announces that the subsequent tracks are to be burned as audio.
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
-swab. Unless marked explicitely by option -data, input files with suffix
-swab. Unless marked explicitly by option -data, input files with suffix
".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
audio track. Same is done for suffix ".au" and SUN Audio.
@ -351,7 +361,7 @@ audio track. Same is done for suffix ".au" and SUN Audio.
Option -audio may be used only with CD media and not with DVD or BD.
.TP
.BI blank= type
Blank a CD-RW, DVD-RW, or format a DVD-RW, DVD+RW, DVD-RAM, BD-RE.
Blank a CD-RW, DVD-RW, or format a DVD-RW, DVD+RW, DVD-RAM, BD.
This is combinable with burning in the same run of cdrskin.
The type given with blank= selects the particular behavior:
.RS
@ -363,7 +373,7 @@ It is a reason to abort if the media cannot assume thoroughly writeable state,
e.g. if it is non-blank write-once.
.br
This leaves unformatted DVD-RW in unformatted blank state. To format DVD-RW use
blank=format_overwriteable.
blank=format_overwriteable. Blank unformatted BD-R stay unformatted.
.br
(Note: blank=as_needed is not an original cdrecord option.)
.TP
@ -392,10 +402,11 @@ This is faster than full blanking but may yield media incapable of
Incremental Streaming (-tao).
.TP
format_if_needed
Format a media if it is not overwriteably formatted yet,
Format a media if it is not formatted yet,
and if cdrskin supports formatting for the media type,
and if formatting will not happen automatically during write.
This currently applies to unformatted DVD-RW, DVD-RAM and BD-RE.
This currently applies to unformatted DVD-RW, DVD-RAM, BD-RE,
and blank unformatted BD-R.
Eventually the appropriate default formatting is chosen.
If other media or states are encountered then nothing happens.
.br
@ -425,7 +436,7 @@ For DVD+RW this is the only supported explicit formatting type. It provides
complete "de-icing" so no reader slips on unwritten data areas.
.TP
format_defectmgt
Format DVD-RAM or BD-RE to reserve the default amount of spare blocks for
Format DVD-RAM or BD to reserve the default amount of spare blocks for
defect management.
.br
The following format_defectmgt_* allow to submit user wishes which
@ -449,25 +460,25 @@ Whether there happens certification at all depends much on the media state
and the actually selected format descriptor.
.TP
format_defectmgt_max
Format DVD-RAM or BD-RE to reserve a maximum number of spare blocks.
Format DVD-RAM or BD to reserve a maximum number of spare blocks.
.TP
format_defectmgt_min
Format DVD-RAM or BD-RE to reserve a minimum number of spare blocks.
Format DVD-RAM or BD to reserve a minimum number of spare blocks.
It might be necessary to format format_defectmgt_none first in order to get
offered the most minmal spare blocks sizes for format_defectmgt_min.
.TP
format_defectmgt_none
Format DVD-RAM or BD-RE to the largest available payload in the hope to disable
defect management at all. This seems not to have a speed increasing effect,
though.
defect management at all. This may or may not have a speed increasing effect.
Unformatted blank BD-R will be left unformatted.
.TP
format_defectmgt_payload_<size>
Format DVD-RAM or BD-RE. The text after "format_defectmgt_payload_" gives a
Format DVD-RAM or BD. The text after "format_defectmgt_payload_" gives a
number of bytes, eventually with suffixes "s", "k", "m". The largest number
of spare blocks will be chosen which allows at least the given payload size.
.TP
format_by_index_<number>
Format DVD-RW, DVD+RW, DVD-RAM or BD-RE.
Format DVD-RW, DVD+RW, DVD-RAM or BD.
The number after "format_by_index_" is used as index to the list of available
format descriptors. This list can be obtained by option --list_formats.
The numbers after text "Format idx" are the ones to be used with
@ -489,7 +500,15 @@ or DVD-R[W] in Disc-at-once mode.
.TP
.BI \-data
Subsequent tracks are data tracks. This option is default and only needed
to mark the end of the range of an eventual option -audio.
to mark the end of the range of an eventual option -audio or -xa1.
.br
Options -mode2, -xa, and -xa2 get mapped to -data, not using the desired CD
sector formats and thus not taking advantage of eventual higher payload.
.BI \-xa1
Subsequent tracks are data tracks with input suitable for CD-ROM XA mode 2
form 1. This differs from -data input by 8 additional header bytes per block.
cdrskin will not write CD-ROM XA but rather strip the header bytes and write as
-data tracks.
.TP
.BI dev= target
Set the address of the drive to use. Valid are at least the
@ -511,7 +530,7 @@ of Bus,Target,Lun addresses.
Set "driveropts=noburnfree" to disable the drive's eventual protection
mechanism against temporary lack of source data (i.e. buffer underrun).
A drive that announces no such capabilities will not get them enabled anyway,
even if attempted explicitely via "driveropts=burnfree".
even if attempted explicitly via "driveropts=burnfree".
.TP
.BI \-dummy
Try to perform the drive operations without actually affecting the inserted
@ -581,7 +600,7 @@ 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
The range of -isosize is exactly one track. Further tracks may be preceded
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
@ -608,6 +627,10 @@ modesty_on_drive=1:min_percent=<percentage>:max_percent=95
.br
Percentage is permissible between 25 and 95.
.TP
.BI -minfo
Print information about the loaded media. This includes media type, writability
state, and a quite readable table of content.
.TP
.BI msifile= 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
@ -617,7 +640,8 @@ Note: msifile=path is actually an option of wodim and not of cdrecord.
.TP
.BI \-msinfo
Retrieve multi-session info for preparing a follow-up session by option -C
of programs mkisofs or genisoimage. Print result to standard output.
of programs mkisofs, genisoimage, or xorriso -as mkisofs.
Print result to standard output.
This option redirects to stderr all message output except the one of option
--tell_media_space and its own result string, which consists of two numbers.
The result string shall be used as argument of option -C with said programs.
@ -629,8 +653,8 @@ To have a chance for working on overwriteable media, this option has to be
accompanied by option --grow_overwriteable_iso.
.TP
.BI \-multi
This option keeps the CD or unformatted DVD-R[W] appendable after the current
session has been written.
This option keeps CD, unformatted DVD-R[W], DVD+R, or BD-R appendable
after the current session has been written.
Without it the disc gets closed and may not be written any more - unless it
is a -RW and gets blanked which causes loss of its content.
.br
@ -670,16 +694,9 @@ Add the given amount of trailing zeros to the next data track. This option
gets reset to padsize=0 after that next track is written. It may be set
again before the next track argument. About size specifiers, see option fs=.
.TP
.BI \-raw96r
Write CD in RAW/RAW96R mode. This mode allows to put more payload bytes
into a CD sector but obviously at the cost of error correction. It can only
be used for tracks of fixely predicted size. Some drives allow this mode but
then behave strange or even go bad for the next few attempts to burn a CD.
One should use it only if inavoidable.
.TP
.BI \-sao
Write CD in Session At Once mode, a sequential DVD-R[W] in Disc-at-once
(DAO) mode, or a DVD+R[/DL].
Write CD in Session At Once mode or sequential DVD-R[W] in Disc-at-once
(DAO) mode.
.br
With CD this mode is able to put several audio tracks on media without
producing audible gaps between them.
@ -687,11 +704,11 @@ producing audible gaps between them.
With DVD-R[W] this mode can only write a single track.
No -multi is allowed with DVD-R[W] -sao.
.br
-sao is permissible with overwriteable DVD, BD or DVD+R[/DL] but actually
-sao is permissible with overwriteable DVD, or DVD+R[/DL], or BD but actually
only imposes restrictions without providing known advantages.
.br
-sao can only be used for tracks of fixely predicted size. This implies that
track arguments which depict stdin or named pipes need to be preceeded by
track arguments which depict stdin or named pipes need to be preceded by
option tsize= or by option tao_to_sao_tsize=.
.br
-sao cannot be used on appendable media.
@ -782,6 +799,11 @@ Level 2 additionally reports about option settings derived from arguments or
startup files. Level 3 is for debugging and useful mainly in conjunction with
somebody who had a look into the program sourcecode.
.TP
.BI \-V
Enable logging of SCSI commands to stderr. This allows expert examination
of the interaction between libburn and the drive. The commands are specified
in SCSI-3 standards SPC, SBC, MMC.
.TP
.BI \-waiti
Wait until input data is available at stdin or EOF occurs at stdin.
Only then begin to access any drives.
@ -803,7 +825,7 @@ Alphabetical list of options which are genuine to cdrskin and intended for
normal use:
.TP
.BI \--adjust_speed_to_drive
Curb explicitely given speed= values to the maximum which is announced by the
Curb explicitly 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.
@ -880,6 +902,14 @@ Both, write_start_address and direct_write_amount size must be aligned to a
media dependend transaction size. With DVD-RAM, BD-RE, DVD+RW this is 2k, with
overwriteable DVD-RW it is 32k.
.TP
.BI dvd_obs= default|32k|64k
Linux specific:
Set the number of bytes to be transmitted with each write operation to DVD
or BD media. Tracks get padded up to the next multiple of this write
size. A number of 64 KB may improve throughput with bus systems which
show latency problems. The default depends on media type, option
stream_recording=, and on compile time options.
.TP
.BI fallback_program= command
Set a command name to be executed if cdrskin encounters a known cdrecord
option which it does not yet support. If a non-empty command is given with
@ -889,7 +919,7 @@ to cdrskin, then cdrskin will delegate the job to said command.
The natural commands to be given are cdrecord or wodim but one may well submit
the address of an own program.
.br
The fallback programm will get all arguments of cdrskin which do not match
The fallback program will get all arguments of cdrskin which do not match
the shell patterns --?* or *_*=* . This eventually suppresses path names of
track sources which happen to match those patterns. The options from the
startup files are not handed to the fallback program.
@ -935,12 +965,12 @@ source is a ISO-9660 filesystem image.
With overwriteable media and no option blank=fast|all present it expands an
eventual ISO-9660 filesystem on media. It is assumed that this image's inner
size description points to the end of the valuable data.
Overwriteable media with a recognizeable ISO-9660 size will be regarded as
Overwriteable media with a recognizable ISO-9660 size will be regarded as
appendable rather than as blank. I.e. options -msinfo and -toc will work.
-toc will always show a single session with its size increasing with
every added mkisofs image.
.br
If not overriden by option write_start_address=, the track with the new image
If not overridden by option write_start_address=, the track with the new image
will be placed behind the end of the old one. One may use option
assert_write_lba= to make sure that media state and mkisofs job do match.
.br
@ -972,6 +1002,10 @@ List all ignored cdrecord options. The "-" options cannot be used as addresses
of track sources. No track source address may begin with a text equal to an
option which ends by "=". The list is ended by an empty line.
.TP
.BI \--long_toc
Like option -toc but marking each session start by a line "first: X last: Y"
and each session end by "track:lout ...".
.TP
.BI \--no_rc
Only if used as first command line argument this option prevents reading and
interpretation of eventual startup files. See section FILES below.
@ -990,6 +1024,22 @@ which can only do DAO but not Incremental Streaming.
.BI \--single_track
Accept only the last argument of the command line as track source address.
.TP
.BI stdio_sync= on|off|number
Set the number of bytes after which to force output to drives with prefix
"stdio:". This forcing keeps the memory from being clogged with lots of
pending data for slow devices. Default "on" is the same as "16m".
Forced output can be disabled by "off".
.TP
.BI stream_recording= on|off|number
By setting "on" request that compliance to the desired speed setting is
preferred over management of write errors. With DVD-RAM and BD this can
bring effective write speed near to the nominal write speed of the media.
But it will also disable the automatic use of replacement blocks
if write errors occur. It might as well be disliked or ignored by the drive.
.br
If a number is given, then error management stays enabled for all byte
addresses below that number. Any number below 16s is the same as "off".
.TP
.BI tao_to_sao_tsize= size
Set an exact fixed size for the next track to be in effect only if the track
source cannot deliver a size prediction and no tsize= was specified and an
@ -1015,7 +1065,7 @@ the available capacity. So for most realistic results one may set up
the full burn session and add --tell_media_space. But if one has to expect
a cdrskin version prior to 0.3.3 no track source should be given in order
not to start an involuntary burn session.
In this case set at least -sao or -tao explicitely.
In this case set at least -sao or -tao explicitly.
.br
The result gets printed to standard output. It is 0 or empty if no writing
is possible with the given options.
@ -1083,7 +1133,7 @@ Wether this leads to senseful behavior depends on operating system and kernel.
Linux specific: Select a SCSI device file family to be scanned for by
options --devices and -scanbus.
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
on kernels >= 2.6 . This option allows to explicitly 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
@ -1176,14 +1226,9 @@ Linux specific:
Use and report literal Bus,Target,Lun addresses rather than real SCSI and
pseudo ATA addresses. This method is outdated and was never compatible with
original cdrecord.
.TP
.BI stream_recording="on"|"off"
By setting "on" request that compliance to the desired speed setting is
preferred over management of write errors. With DVD-RAM and BD-RE this can
bring effective write speed near to the nominal write speed of the media.
But it will also disable the automatic use of replacement blocks
if write errors occur. It might as well be disliked or ignored by the drive.
.br
.BI --xa1-ignore
Silently interpret option -xa1 as -data. This may be necessary if a frontent
does not prepare -xa1 block headers but insists in using option -xa1.
.SH EXAMPLES
.SS
.B Get an overview of drives and their addresses:
@ -1200,7 +1245,7 @@ cdrskin dev=0,1,0 -checkdrive
.br
cdrskin dev=ATA:1,0,0 -v -atip
.br
cdrskin dev=/dev/hdc -toc
cdrskin dev=/dev/hdc -minfo
.SS
.B Prepare CD-RW or DVD-RW for re-use, DVD-RAM or BD-RE for first use:
.br
@ -1228,15 +1273,15 @@ cdrskin -v dev=0,1,0 fs=32m speed=8 \\
.br
blank=as_needed padsize=300k -
.SS
.B Write multi-session to the same CD, DVD-R[W] or DVD+R[/DL]:
.B Write multi-session to the same CD, DVD-R[W], DVD+R[/DL], or BD-R:
.br
cdrskin dev=/dev/hdc -v padsize=300k -multi 1.iso
cdrskin dev=/dev/sr0 -v padsize=300k -multi 1.iso
.br
cdrskin dev=/dev/hdc -v padsize=300k -multi 2.iso
cdrskin dev=/dev/sr0 -v padsize=300k -multi 2.iso
.br
cdrskin dev=/dev/hdc -v padsize=300k -multi 3.iso
cdrskin dev=/dev/sr0 -v padsize=300k -multi 3.iso
.br
cdrskin dev=/dev/hdc -v padsize=300k 4.iso
cdrskin dev=/dev/sr0 -v padsize=300k 4.iso
.SS
.B Get multi-session info for option -C of program mkisofs:
.br

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
<HEAD>
<META NAME="description" CONTENT="cdrskin, a limited cdrecord compatibility wrapper for libburn">
<META NAME="keywords" CONTENT="cdrskin, libburn, libburnia, burn, CD, DVD, linux, recording, burning, CD-R, CD-RW, DVD-R, DVD-RW, DVD+RW, DVD+R, DVD+R/DL, DVD-RAM, BD-RE, cdrecord, compatible, scdbackup">
<META NAME="keywords" CONTENT="cdrskin, libburn, libburnia, burn, CD, DVD, linux, recording, burning, CD-R, CD-RW, DVD-R, DVD-RW, DVD+RW, DVD+R, DVD+R/DL, DVD-RAM, BD-RE, BD-R, cdrecord, compatible, scdbackup">
<META NAME="robots" CONTENT="follow">
<TITLE>cdrskin homepage english</TITLE>
</HEAD>
@ -24,7 +24,7 @@
<P>
<H2>Purpose:</H2>
Burns preformatted data to CD, DVD, and BD media:<BR>
CD-R, DVD-R, DVD+R, DVD+R/DL, CD-RW, DVD-RW, DVD-RAM, DVD+RW, BD-RE
CD-R, DVD-R, DVD+R, DVD+R/DL, BD-R, CD-RW, DVD-RW, DVD-RAM, DVD+RW, BD-RE
</P>
<P>
@ -34,10 +34,12 @@ CD-R, DVD-R, DVD+R, DVD+R/DL, CD-RW, DVD-RW, DVD-RAM, DVD+RW, BD-RE
<P>
<H2>Hardware requirements:</H2>
A CD/DVD/BD recorder suitable for
<A HREF="http://libburnia-project.org">http://libburnia-project.org</A> <BR>
(SCSI , ATA , USB , or SATA writers compliant to standard MMC-3 for CD
and to MMC-5 for DVD or BD).
About any CD, DVD, or BD recorder produced in the recent ten years.
<BR>
<A HREF="http://libburnia-project.org">libburn</A>
supports recorders which are compliant to standards MMC-1 for CD and
MMC-5 for DVD or BD. Linux, FreeBSD, and Solaris allow to access drives
connected via SCSI, PATA (aka IDE, ATA), USB, or SATA.
<BR>
</P>
@ -47,6 +49,11 @@ and to MMC-5 for DVD or BD).
<DT>Linux with kernel 2.4 or higher (and libc, of course) :</DT>
<DD>With kernel 2.4 an ATA drive has to be under ide-scsi emulation.</DD>
<DD>With kernel 2.6 the drive should not be under ide-scsi.</DD>
<DT>or FreeBSD (with libc, of course) :</DT>
<DD>ATA and SATA drives need atapicam running.</DD>
<DD>libcam has to be installed.</DD>
<DT>or Solaris (with libc, of course) :</DT>
<DD>Tested on kernel 5.11, hopefully suitable for older ones too.</DD>
<DT>libpthread</DT>
<DD>is supposed to be a standard system component.</DD>
</DL>
@ -57,15 +64,18 @@ and to MMC-5 for DVD or BD).
GPL software included:<BR>
</H2>
<DL>
<DT>libburn-0.5.0</DT>
<DT>libburn-0.8.2</DT>
<DD>(founded by Derek Foreman and Ben Jansens,
furthered since August 2006 by Thomas Schmitt from team of libburnia-project.org)</DD>
<DD>transfers data to CD, DVD, BD-RE</DD>
developed and maintained since August 2006 by
Thomas Schmitt from team of libburnia-project.org)
</DD>
<DD>transfers data to CD, DVD, BD</DD>
</DL>
</P>
<P>
This program system has been tested on Intel/AMD Linux systems only.<BR>
This program system has been tested on Intel/AMD with Linux, FreeBSD,
and OpenSolaris based operating systems.<BR>
Ports to other usable systems are appreciated. Reports are welcome.
</P>
@ -88,7 +98,7 @@ are provided in a compatible way.<BR>
On all DVD media except DVD-R DL, cdrskin is able to perform any recording job
which is possible with cdrecord.
Other than with cdrecord, option -multi is supported with many DVD types and
write mode -tao works with anything but quickly blanked DVD-RW.
BD-R. Write mode -tao works with anything but quickly blanked DVD-RW.
</DT>
<BR><BR>
<DT>Get an overview of drives and their addresses</DT>
@ -97,14 +107,15 @@ write mode -tao works with anything but quickly blanked DVD-RW.
<DD>#<KBD>&nbsp;cdrskin --devices</KBD></DD>
<DT>Being superuser avoids permission problems with /dev/srN resp. /dev/hdX .
</DT>
<DT>Ordinary users should then get granted rw access to the /dev files
as listed by option --devices.</DT>
<DT>Ordinary users should then get granted access to the /dev files
as listed by option --devices. Linux and FreeBSD demand rw-permission.
On Solaris it is r-permission and privileges "basic,sys_devices".</DT>
<DT>&nbsp;</DT>
<DT>Get info about a particular drive or loaded media:</DT>
<DD>$<KBD>&nbsp;cdrskin dev=0,1,0 -checkdrive</KBD></DD>
<DD>$<KBD>&nbsp;cdrskin dev=ATA:1,0,0 -v -atip</KBD></DD>
<DD>$<KBD>&nbsp;cdrskin dev=/dev/hdc -toc</KBD></DD>
<DD>$<KBD>&nbsp;cdrskin dev=/dev/hdc -minfo</KBD></DD>
<DT>Prepare CD-RW or DVD-RW for re-use, DVD-RAM or BD-RE for first use:</DT>
<DD>$<KBD>&nbsp;cdrskin -v dev=/dev/sg1 blank=as_needed -eject</KBD></DD>
@ -143,6 +154,9 @@ as listed by option --devices.</DT>
<DD><KBD>&nbsp;&nbsp;--tell_media_space 2>/dev/null)</KBD></DD>
<DD>$<KBD>&nbsp;echo "Available: $x blocks of 2048 data bytes"</KBD></DD>
<DT>Accelerate BD-RE writing to full nominal speed after the first 250 MB</DT>
<DD>$<KBD>&nbsp;cdrskin ... stream_recording=250m ...</KBD>
<DT>Write audio tracks to CD:</DT>
<DD>$<KBD>&nbsp;cdrskin -v dev=ATA:1,0,0 speed=48 -sao \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;track1.wav track2.au -audio -swab track3.raw</KBD></DD>
@ -169,14 +183,11 @@ man cdrecord</A></KBD></DD>
<DL>
<DT>Learn to know a more versatile way to burn ISO 9660 formatted data</DT>
<DD>
Standalone ISO 9660 multi-session CD/DVD tool
Standalone ISO 9660 multi-session CD/DVD/BD tool
<A HREF="http://scdbackup.sourceforge.net/xorriso_eng.html">xorriso</A>.
</DD>
</DL>
Testers wanted who are willing to risk some DVD-R DL media
or to do experiments on BD-R media.
</P>
<HR>
@ -186,8 +197,8 @@ or to do experiments on BD-R media.
<P>
<DL>
<DT>Download as source code (see README):</DT>
<DD><A HREF="cdrskin-0.5.0.pl00.tar.gz">cdrskin-0.5.0.pl00.tar.gz</A>
(730 KB).
<DD><A HREF="cdrskin-0.8.2.pl00.tar.gz">cdrskin-0.8.2.pl00.tar.gz</A>
(845 KB).
</DD>
<DD>
The cdrskin tarballs are source code identical with libburn releases
@ -236,40 +247,59 @@ cdrskin_0.4.2.pl00-x86-suse9_0-static.tar.gz</A>, (310 KB), -static compiled,
<HR>
<P>
Enhancements towards previous stable version cdrskin-0.4.8.pl00:
Enhancements towards previous stable version cdrskin-0.8.0.pl00:
<UL>
<LI>Ability to use /dev/scdN as fallback if /dev/srN does not exist</LI>
<LI>A new system adapter allows to burn CD, DVD and BD on OpenSolaris</LI>
<!--
<LI>none</LI>
-->
</UL>
Bug fixes towards cdrskin-0.4.8.pl00:
Bug fixes towards cdrskin-0.8.0.pl00:
<UL>
<LI>Option drive_scsi_dev_family=scd lead to buffer overflow</LI>
<LI>
CD TOC was not read if the first track did not start at LBA 0
</LI>
<LI>
CD-ROM media got attributed random lead-in and lead-out adresses
</LI>
<LI>
SIGSEGV of experimental libcdio system adapter if drive list is empty
</LI>
<!--
<LI>none</LI>
-->
</UL>
</P>
<HR>
<P>
<DL>
<DT><H3>Development snapshot, version 0.5.1 :</H3></DT>
<DD>Enhancements towards current stable version 0.5.0.pl00:
<DT><H3>Development snapshot, version 0.8.3 :</H3></DT>
<DD>Enhancements towards current stable version 0.8.2.pl00:
<UL>
<LI>none yet</LI>
<!--
<LI>none yet</LI>
-->
<LI>Larger set of possibly acceptable drive device file names</LI>
</UL>
</DD>
<DD>Bug fixes towards cdrskin-0.8.2.pl00:
<UL>
<LI>none yet</LI>
<!--
<LI>none yet</LI>
-->
</UL>
</DD>
<DD>&nbsp;</DD>
<DD><A HREF="README_cdrskin_devel">README 0.5.1</A>
<DD><A HREF="cdrskin__help_devel">cdrskin_0.5.1 --help</A></DD>
<DD><A HREF="cdrskin_help_devel">cdrskin_0.5.1 -help</A></DD>
<DD><A HREF="man_1_cdrskin_devel.html">man cdrskin (as of 0.5.1)</A></DD>
<DD><A HREF="README_cdrskin_devel">README 0.8.3</A>
<DD><A HREF="cdrskin__help_devel">cdrskin_0.8.3 --help</A></DD>
<DD><A HREF="cdrskin_help_devel">cdrskin_0.8.3 -help</A></DD>
<DD><A HREF="man_1_cdrskin_devel.html">man cdrskin (as of 0.8.3)</A></DD>
<DD>&nbsp;</DD>
<DT>Maintainers of cdrskin unstable packages please use SVN of
<A HREF="http://libburnia-project.org"> libburnia-project.org</A></DT>
@ -289,8 +319,8 @@ admins with full system souvereignty.</DT>
<A HREF="README_cdrskin_devel">upcoming README</A> ):
</DD>
<DD>
<A HREF="cdrskin-0.5.1.tar.gz">cdrskin-0.5.1.tar.gz</A>
(730 KB).
<A HREF="cdrskin-0.8.3.tar.gz">cdrskin-0.8.3.tar.gz</A>
(845 KB).
</DD>
<!-- This is not offered any more since spring 2008
@ -323,7 +353,7 @@ Historic versions based on Derek's and Ben's
<BR>
Very special thanks to Andy Polyakov whose
<A HREF="http://fy.chalmers.se/~appro/linux/DVD+RW/tools">dvd+rw-tools</A>
provide libburn with invaluable examples on how to deal with DVD media.
provide libburn with invaluable examples on how to deal with DVD and BD media.
</P>
<HR>
@ -485,12 +515,17 @@ and by <A HREF="http://sourceforge.net">sourceforge.net</A><BR>
<A href="http://sourceforge.net">
<IMG src="sflogo-88-1.png" BORDER="0" ALT="SourceForge Logo"></A>
<!-- on sourceforge use : <IMG src="http://sourceforge.net/sflogo.php?group_id=16010" width="88" height="31" border="0" alt="SourceForge Logo"></A> -->
<P>
Enjoying a FreeBSD shell account with the opportunity to
build and install cdrskin at<BR>
<A HREF="http://www.en.free-shells.com.ar">free-shells.com.ar</A>
</P>
</FONT></CENTER>
<HR>
<DL>
<DT>Links to my other published software projects :
<DD><A HREF="http://scdbackup.webframe.org/xorriso_eng.html">
xorriso, a standalone ISO 9660 multi-session CD/DVD burn tool.
xorriso, a standalone ISO 9660 multi-session CD/DVD/BD burn tool.
No mkisofs needed.
<DL>
<DD>

View File

@ -1 +1 @@
#define Cdrskin_timestamP "2008.08.19.123513"
#define Cdrskin_timestamP "2010.06.11.080001"

File diff suppressed because it is too large Load Diff

View File

@ -1,24 +1,38 @@
#!/bin/sh
# compile_cdrskin.sh
# Copyright 2005 - 2008 Thomas Schmitt, scdbackup@gmx.net, GPL version 2
# Copyright 2005 - 2010 Thomas Schmitt, scdbackup@gmx.net, GPL
# to be executed within ./libburn-* resp ./cdrskin-*
debug_opts="-O2"
def_opts=
largefile_opts="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1"
libvers="-DCdrskin_libburn_0_5_1"
cleanup_src_or_obj="libburn/cleanup.o"
libdax_msgs_o="libburn/libdax_msgs.o"
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
fifo_opts=""
libvers="-DCdrskin_libburn_0_8_2"
# To be used if Makefile.am uses libburn_libburn_la_CFLAGS
# burn="libburn/libburn_libburn_la-"
burn="libburn/"
cleanup_src_or_obj="$burn"cleanup.o
libdax_msgs_o="$burn"libdax_msgs.o
libdax_audioxtr_o="$burn"libdax_audioxtr.o
do_strip=0
static_opts=
warn_opts="-Wall"
libcdio=
fifo_source="cdrskin/cdrfifo.c"
compile_cdrskin=1
compile_cdrfifo=0
compile_dewav=0
libcam=
os=$(uname -s)
case $os in
*FreeBSD)
libcam="-lcam"
esac
for i in "$@"
do
if test "$i" = "-compile_cdrfifo"
@ -31,20 +45,20 @@ do
then
libvers="-DCdrskin_libburn_cvs_A60220_tS"
libdax_audioxtr_o=
libdax_msgs_o="libburn/message.o"
libdax_msgs_o="$burn"message.o
cleanup_src_or_obj="-DCleanup_has_no_libburn_os_H cdrskin/cleanup.c"
elif test "$i" = "-libburn_0_5_0"
elif test "$i" = "-libburn_0_8_2"
then
libvers="-DCdrskin_libburn_0_5_0"
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
libdax_msgs_o="libburn/libdax_msgs.o"
cleanup_src_or_obj="libburn/cleanup.o"
libvers="-DCdrskin_libburn_0_8_2"
libdax_audioxtr_o="$burn"libdax_audioxtr.o
libdax_msgs_o="$burn"libdax_msgs.o
cleanup_src_or_obj="$burn"cleanup.o
elif test "$i" = "-libburn_svn"
then
libvers="-DCdrskin_libburn_0_5_1"
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
libdax_msgs_o="libburn/libdax_msgs.o"
cleanup_src_or_obj="libburn/cleanup.o"
libvers="-DCdrskin_libburn_0_8_3"
libdax_audioxtr_o="$burn"libdax_audioxtr.o
libdax_msgs_o="$burn"libdax_msgs.o
cleanup_src_or_obj="$burn"cleanup.o
elif test "$i" = "-newapi" -o "$i" = "-experimental"
then
def_opts="$def_opts -DCdrskin_new_api_tesT"
@ -55,6 +69,9 @@ do
elif test "$i" = "-no_largefile"
then
largefile_opts=
elif test "$i" = "-dvd_obs_64k"
then
def_opts="$def_opts -DCdrskin_dvd_obs_default_64K"
elif test "$i" = "-do_not_compile_cdrskin"
then
compile_cdrskin=0
@ -66,6 +83,23 @@ do
elif test "$i" = "-do_strip"
then
do_strip=1
elif test "$i" = "-use_libburn_fifo"
then
fifo_opts="-DCdrskin_use_libburn_fifO"
elif test "$i" = "-use_no_libburn_fifo"
then
fifo_opts=""
elif test "$i" = "-use_no_cdrfifo"
then
fifo_source=
fifo_opts="-DCdrskin_use_libburn_fifO -DCdrskin_no_cdrfifO"
elif test "$i" = "-use_libburn_cleanup"
then
fifo_source=
fifo_opts="-DCdrskin_use_libburn_cleanuP -DCdrskin_use_libburn_fifO -DCdrskin_no_cdrfifO"
elif test "$i" = "-use_libcdio"
then
libcdio="-lcdio"
elif test "$i" = "-g"
then
debug_opts="-g"
@ -75,11 +109,13 @@ do
echo "Options:"
echo " -compile_cdrfifo compile program cdrskin/cdrfifo."
echo " -compile_dewav compile program test/dewav without libburn."
echo " -cvs_A60220 set macro to match libburn-CVS of 20 Feb 2006."
echo " -libburn_0_5_0 set macro to match libburn-0.5.0"
echo " -libburn_0_8_2 set macro to match libburn-0.8.2"
echo " -libburn_svn set macro to match current libburn-SVN."
echo " -no_largefile do not use 64 bit off_t (must match libburn)."
echo " -dvd_obs_64k 64 KB default size for DVD/BD writing."
echo " -use_libcdio link with -lcdio because libburn uses it."
echo " -do_not_compile_cdrskin omit compilation of cdrskin/cdrskin."
echo " -use_no_libburn_fifo use cdrfifo even for single track non-CD"
echo " -use_no_cdrfifo always use fifo of libburn and never cdrfifo"
echo " -experimental use newly introduced libburn features."
echo " -oldfashioned use pre-0.2.2 libburn features only."
echo " -do_diet produce capability reduced lean version."
@ -100,13 +136,14 @@ echo "Build timestamp : $timestamp"
if test "$compile_cdrskin"
then
echo "compiling program cdrskin/cdrskin.c $static_opts $debug_opts $libvers $def_opts $cleanup_src_or_obj"
echo "compiling program cdrskin/cdrskin.c $fifo_source $static_opts $debug_opts $libvers $fifo_opts $def_opts $cleanup_src_or_obj $libcdio $libcam"
cc -I. \
$warn_opts \
$static_opts \
$debug_opts \
$libvers \
$largefile_opts \
$fifo_opts \
$def_opts \
\
-DCdrskin_build_timestamP='"'"$timestamp"'"' \
@ -118,32 +155,34 @@ then
\
$cleanup_src_or_obj \
\
libburn/async.o \
libburn/debug.o \
libburn/drive.o \
libburn/file.o \
libburn/init.o \
libburn/options.o \
libburn/source.o \
libburn/structure.o \
"$burn"async.o \
"$burn"debug.o \
"$burn"drive.o \
"$burn"file.o \
"$burn"init.o \
"$burn"options.o \
"$burn"source.o \
"$burn"structure.o \
\
libburn/sg.o \
libburn/write.o \
libburn/read.o \
"$burn"sg.o \
"$burn"write.o \
"$burn"read.o \
$libdax_audioxtr_o \
$libdax_msgs_o \
\
libburn/mmc.o \
libburn/sbc.o \
libburn/spc.o \
libburn/util.o \
"$burn"mmc.o \
"$burn"sbc.o \
"$burn"spc.o \
"$burn"util.o \
\
libburn/sector.o \
libburn/toc.o \
"$burn"sector.o \
"$burn"toc.o \
\
libburn/crc.o \
libburn/lec.o \
"$burn"crc.o \
"$burn"ecma130ab.o \
\
$libcdio \
$libcam \
-lpthread
ret=$?
@ -185,8 +224,8 @@ then
-DDewav_without_libburN \
-o test/dewav \
test/dewav.c \
libburn/libdax_audioxtr.o \
libburn/libdax_msgs.o \
"$burn"libdax_audioxtr.o \
"$burn"libdax_msgs.o \
\
-lpthread

View File

@ -10,8 +10,8 @@ Schilling's cdrtools. cdrskin strives to be a second source for the services
traditionally provided by cdrecord. Currently it does CD-R and CD-RW this way.
Overwriteable media DVD-RAM, DVD+RW, DVD-RW, and BD-RE are handled differently
than with cdrecord-ProDVD in order to offer TAO-like single track recording.
Sequential DVD-R[W], DVD+R, DVD+R DL are handled like CD-R[W] with TAO and
multi-session. Additionally cdrskin offers cdrecord-ProDVD-like mode DAO
Sequential DVD-R[W], DVD+R, DVD+R DL, BD-R are handled like CD-R[W] with TAO
and multi-session. Additionally cdrskin offers cdrecord-ProDVD-like mode DAO
with DVD-R[W].
cdrskin does not contain any bytes copied from cdrecord's sources.

View File

@ -1,13 +1,15 @@
AC_INIT([libburn], [0.5.1], [http://libburnia-project.org])
AC_INIT([libburn], [0.8.2], [http://libburnia-project.org])
AC_PREREQ([2.50])
dnl AC_CONFIG_HEADER([config.h])
AC_CANONICAL_HOST
AC_CANONICAL_TARGET
LIBBURNIA_SET_FLAGS
AM_INIT_AUTOMAKE([subdir-objects])
dnl Notes by ts A71207 - A80126 :
dnl Notes by ts A71207 - B00611 :
dnl
dnl Regrettably the meaning of the various version types was misunderstood
dnl before version 0.4.1.
@ -42,7 +44,8 @@ dnl So this is a superspace of the SONAME version space. To avoid
dnl ill SONAME, the value of CURRENT must be larger than AGE.
dnl See also http://www.gnu.org/software/libtool/manual.html#Interfaces
dnl
dnl The name of the dynamic library will be libburn.so.$SONAME.$AGE.$REV .
dnl On Linux the name of the dynamic library will be
dnl libburn.so.$SONAME.$AGE.$REV
dnl In the terminology of this file:
dnl CURRENT = LT_CURRENT
dnl AGE = LT_AGE
@ -63,6 +66,22 @@ dnl 0.4.4 = libburn.so.4.9.0
dnl 0.4.6 = libburn.so.4.11.0
dnl 0.4.8 = libburn.so.4.13.0
dnl 0.5.0 = libburn.so.4.15.0
dnl 0.5.2 = libburn.so.4.17.0
dnl 0.5.4 = libburn.so.4.19.0
dnl 0.5.6 = libburn.so.4.21.0
dnl 0.5.8 = libburn.so.4.23.0
dnl 0.6.0 = libburn.so.4.25.0
dnl 0.6.2 = libburn.so.4.27.0
dnl 0.6.4 = libburn.so.4.29.0
dnl 0.6.6 = libburn.so.4.31.0
dnl 0.6.8 = libburn.so.4.33.0
dnl 0.7.0 = libburn.so.4.35.0
dnl 0.7.2 = libburn.so.4.37.0
dnl 0.7.4 = libburn.so.4.39.0
dnl 0.7.6 = libburn.so.4.41.0
dnl 0.7.8 = libburn.so.4.43.0
dnl 0.8.0 = libburn.so.4.45.0
dnl 0.8.2 = libburn.so.4.47.0
dnl
dnl So LT_CURRENT, LT_REVISION and LT_AGE get set directly here.
dnl SONAME of the emerging library is LT_CURRENT - LT_AGE.
@ -87,8 +106,8 @@ dnl If BURN_*_VERSION changes, be sure to change AC_INIT above to match.
dnl
dnl As said: Only copies. Original in libburn/libburn.h : burn_header_version_*
BURN_MAJOR_VERSION=0
BURN_MINOR_VERSION=5
BURN_MICRO_VERSION=1
BURN_MINOR_VERSION=8
BURN_MICRO_VERSION=2
BURN_VERSION=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION
AC_SUBST(BURN_MAJOR_VERSION)
@ -99,15 +118,15 @@ AC_SUBST(BURN_VERSION)
dnl Libtool versioning
LT_RELEASE=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION
dnl
dnl ts A80716
dnl ### This is the release version libburn-0.5.0 = libburn.so.4.15.0
dnl This is the development version after above release version
dnl ts B00409
dnl This is the release version libburn-0.8.2
dnl ### This is the development version after above release version
dnl LT_CURRENT++, LT_AGE++ has not yet happened.
dnl ### LT_CURRENT++, LT_AGE++ has happened meanwhile.
dnl
dnl SONAME = 19 - 15 = 4 . Library name = libburn.so.4.15.0
LT_CURRENT=19
LT_AGE=15
dnl SONAME = 51 - 47 = 4 . Linux library name = libburn.so.4.47.0
LT_CURRENT=51
LT_AGE=47
LT_REVISION=0
LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
@ -154,8 +173,76 @@ AC_SUBST(THREAD_LIBS)
TARGET_SHIZZLE
AC_SUBST(ARCH)
AC_SUBST(LIBBURNIA_PKGCONFDIR)
AC_SUBST(LIBBURN_ARCH_LIBS)
dnl ts A90303
dnl Check the preconditions for using statvfs() in sg-dummy
dnl (sg-linux and sg-freebsd use statvfs() unconditionally)
STATVFS_DEF=-DLibburn_os_has_statvfS
AC_CHECK_HEADER(sys/statvfs.h, X=, STATVFS_DEF=)
AC_CHECK_FUNC([statvfs], X=, STATVFS_DEF=)
dnl If this would be done more specifically in Makefile.am
dnl via libburn_libburn_la_CFLAGS then undesired .o file names would emerge
CFLAGS="$CFLAGS $STATVFS_DEF"
dnl ts A91122
AC_ARG_ENABLE(track-src-odirect,
[ --enable-track-src-odirect Enable use of O_DIRECT with track input, default=no],
, enable_track_src_odirect=no)
if test x$enable_track_src_odirect = xyes; then
LIBBURN_O_DIRECT_DEF="-DLibburn_read_o_direcT"
echo "enabled use of O_DIRECT with track input"
else
LIBBURN_O_DIRECT_DEF=
echo "disabled use of O_DIRECT with track input"
fi
dnl Avoid the need for libburn_libburn_la_CFLAGS in Makefile.am (ugly .o names)
dnl ### AC_SUBST(LIBBURN_O_DIRECT_DEF)
CFLAGS="$CFLAGS $LIBBURN_O_DIRECT_DEF"
dnl ts A91116
AC_ARG_ENABLE(dvd-obs-64k,
[ --enable-dvd-obs-64k 64 KB default size for DVD/BD writing, default=no],
, enable_dvd_obs_64k=no)
if test x$enable_dvd_obs_64k = xyes; then
LIBBURN_DVD_OBS_64K="-DLibburn_dvd_obs_default_64K"
echo "enabled write size default 64 KB on DVD and BD"
else
LIBBURN_DVD_OBS_64K=
echo "disabled write size default 64 KB on DVD and BD"
fi
CFLAGS="$CFLAGS $LIBBURN_DVD_OBS_64K"
dnl ts A91218
AC_ARG_ENABLE(libcdio,
[ --enable-libcdio Enable EXPERIMENTAL use of libcdio as system adapter, default=no],
, enable_libcdio=no)
if test x$enable_libcdio = xyes; then
dnl Check whether there is libcdio-devel and libcdio-runtime.
dnl If not, erase this macro
LIBCDIO_DEF="-DLibburn_use_libcdiO"
dnl The empty yes case obviously causes -lcdio to be linked
AC_CHECK_HEADER(cdio/cdio.h, AC_CHECK_LIB(cdio, mmc_last_cmd_sense, , LIBCDIO_DEF= ), LIBCDIO_DEF= )
else
LIBCDIO_DEF=
fi
if test x$LIBCDIO_DEF = x
then
if test x$enable_libcdio = xyes
then
echo "WARNING: could not enable use of libcdio as system adapter"
fi
else
echo "enabled EXPERIMENTAL use of libcdio as system adapter"
CFLAGS="$CFLAGS $LIBCDIO_DEF"
LIBCDIO_REQUIRED=0.83
PKG_CHECK_MODULES(LIBCDIO, libcdio >= $LIBCDIO_REQUIRED)
fi
dnl Add compiler-specific flags
dnl See if the user wants aggressive optimizations of the code
@ -175,6 +262,12 @@ else
CFLAGS="$CFLAGS -DDEBUG"
fi
dnl Determine target directory for libburn-*.pc
dnl Important: Must be performed _after_ TARGET_SHIZZLE
dnl
LIBBURNIA_SET_PKGCONFIG
AC_CONFIG_FILES([
Makefile
doc/doxygen.conf

View File

@ -1,106 +1,51 @@
/**
@author Mario Danic, Thomas Schmitt
@mainpage Libburnia Documentation Index
@mainpage Libburn Documentation Index
@section intro Introduction
Libburnia is an open-source project for reading, mastering and writing
optical discs.
optical discs. This page is about its capability to handle optical media.
For now this means CD-R, CD-RW, DVD-RAM, DVD+RW, DVD+R, DVD+R/DL, DVD-RW,
DVD-R, BD-RE.
DVD-R, BD-R, BD-RE.
Not supported yet are DVD-R/DL, HD-DVD, BD-R (blue ray). Testers for
DVD-R/DL are wanted, though. BD-R programming efforts would be made
if an interested tester contacts us.
Not supported yet are DVD-R/DL. Testers wanted.
The project comprises of several more or less interdependent parts which
together strive to be a usable foundation for application development.
These are libraries, language bindings, and middleware binaries which emulate
classical (and valuable) Linux tools.
Our scope is currently Linux 2.4 and 2.6, or FreeBSD . For ports to other
systems we would need : login on a development machine resp. a live OS on CD
or DVD, advise from a system person about the equivalent of Linux sg or FreeBSD
CAM, volunteers for testing of realistic use cases.
Our scope is currently Linux 2.4 and 2.6 only. For ports to other systems
we would need : login on a development machine resp. a live OS on CD or DVD,
advise from a system person about the equivalent of Linux sg or FreeBSD CAM,
volunteers for testing of realistic use cases.
libburn is the library by which preformatted data get onto optical media.
Its code is independent of cdrecord. Its DVD capabilities are learned from
studying the code of dvd+rw-tools and MMC-5 specs. No code but only the pure
SCSI knowledge has been taken from dvd+rw-tools, though.
We have a well tested code base for burning data and audio CDs and many DVD
types. The burn API is quite comprehensively documented and can be used to
build a presentable application.
We have a functional binary which emulates the core use cases of cdrecord in
order to prove that usability, and in order to allow you to explore libburn's
scope by help of existing cdrecord frontends.
cdrskin is a limited cdrecord compatibility wrapper for libburn.
cdrecord is a powerful GPL'ed burn program included in Joerg Schilling's
cdrtools. cdrskin strives to be a second source for the services traditionally
provided by cdrecord. Additionally it provides libburn's DVD/BD capabilities,
where only -sao is compatible with cdrecord.
cdrskin does not contain any bytes copied from cdrecord's sources.
Many bytes have been copied from the message output of cdrecord runs, though.
See cdrskin/README for more.
ISO 9660 filesystems with Rock Ridge and Joliet extensions can be created
and manipulated quite freely. This capability together with our burn capability
makes possible a single binary application which covers all steps of image
composition, updating and writing. Quite unique in the Linux world.
The burn API example of libburn is named test/libburner.c . The API for media
information inquiry is demonstrated in test/telltoc.c .
Explore these examples if you look for inspiration.
@subsection components The project components (list subject to growth, hopefully):
- 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
/dev/srM or /dev/hdX (e.g. on kernel 2.6).
libburn is the foundation of our cdrecord emulation. Its code is
independent of cdrecord. Its DVD capabilities are learned from
studying the code of dvd+rw-tools and MMC-5 specs. No code but only
the pure SCSI knowledge has been taken from dvd+rw-tools, though.
- libisofs is the library to pack up hard disk files and directories into a
ISO 9660 disk image. This may then be brought to CD via libburn.
libisofs is to be the foundation of our upcoming mkisofs emulation.
- libisoburn is an add-on to libburn and libisofs which coordinates both and
also allows to grow ISO-9660 filesystem images on multi-session
media as well as on overwriteable media via the same API.
All media peculiarities are handled automatically.
- cdrskin is a limited cdrecord compatibility wrapper for libburn.
cdrecord is a powerful GPL'ed burn program included in Joerg
Schilling's cdrtools. cdrskin strives to be a second source for
the services traditionally provided by cdrecord. Additionally it
provides libburn's DVD/BD capabilities, where only -sao is
compatible with cdrecord.
cdrskin does not contain any bytes copied from cdrecord's sources.
Many bytes have been copied from the message output of cdrecord
runs, though.
See cdrskin/README for more.
- xorriso is an application of all three libraries which creates, loads,
manipulates and writes ISO 9660 filesystem images with
Rock Ridge extensions. Manipulation is not only adding or
overwriting of files but also deletion, renaming, and attribute
changing. An incremental backup feature is provided.
See xorriso/README for more
- "test" is a collection of application gestures and examples given by the
authors of the library features. The burn API example of libburn
is named test/libburner.c . The API for media information inquiry is
demonstrated in test/telltoc.c .
Explore these examples if you look for inspiration.
We strive to be a responsive upstream.
Our libraries are committed to maintain older feature sets in newer versions.
This applies to source code headers (API) as well as to linkable objects (ABI).
The only exception from this rule is about non-release versions x.y.*[13579]
which are allowed to introduce new features, change those new features in
any way and even may revoke such new features before the next release of
x.y.*[02468]. As soon as it is released, a feature is promised to persist.
SONAMES:
SONAME:
libburn.so.4 (since 0.3.4, March 2007),
libisofs.so.6 (since 0.6.2, February 2008),
libisoburn.so.1 (since 0.1.0, February 2008).
@section using Using the libraries
@section using Using libburn
Our build system is based on autotools.
User experience tells us that you will need at least autotools version 1.7.
To build libburn and its subprojects it should be sufficient to go into
its toplevel directory and execute
To build libburn and its companion applications go into its toplevel directory
and execute
- ./bootstrap (needed if you downloaded from SVN)
@ -112,30 +57,25 @@ To make the libraries accessible for running resp. developing applications
- make install
Both libraries are written in C language and get built by autotools.
Thus we expect them to be useable by a wide range of Linux-implemented
languages and development tools.
@section libburner Libburner
libburner is a minimal demo application for the library libburn
(see: libburn/libburn.h) as provided on http://libburnia-project.org .
It can list the available devices, can blank a CD-RW or DVD-RW and
can burn to recordable CD and recordable single layer DVD.
It can list the available devices, can burn to recordable CD, DVD, or BD,
can blank a CD-RW or DVD-RW, and can format unformatted DVD-RW, BD-R, or BD-RE.
It's main purpose, nevertheless, is to show you how to use libburn and also
to serve the libburnia team as reference application. libburner does indeed
define the standard way how above three gestures can be implemented and
stay upward compatible for a good while.
define the standard way how above gestures can be implemented and stay upward
compatible for a good while.
@subsection libburner-help Libburner --help
<pre>
Usage: test/libburner
[--drive <address>|<driveno>|"-"] [--audio]
[--blank_fast|--blank_full|--format_overwrite]
[--try_to_simulate]
[--multi] [<one or more imagefiles>|"-"]
[--drive address|driveno|"-"] [--audio]
[--blank_fast|--blank_full|--format] [--try_to_simulate]
[--multi] [one or more imagefiles|"-"]
Examples
A bus scan (needs rw-permissions to see a drive):
test/libburner --drive -
@ -147,8 +87,8 @@ Blank a used CD-RW (is combinable with burning in one run):
test/libburner --drive /dev/hdc --blank_fast
Blank a used DVD-RW (is combinable with burning in one run):
test/libburner --drive /dev/hdc --blank_full
Format a DVD-RW to avoid need for blanking before re-use:
test/libburner --drive /dev/hdc --format_overwrite
Format a DVD-RW, BD-RE or BD-R:
test/libburner --drive /dev/hdc --format
Burn two audio tracks (to CD only):
lame --decode -t /path/to/track1.mp3 track1.cd
test/dewav /path/to/track2.wav -o track2.cd

View File

@ -1,4 +1,4 @@
libburnia-project.org Optical Media Rotisserie Recipes as of April 2008
libburnia-project.org Optical Media Rotisserie Recipes as of January 2010
Content:
- TAO Multi-Session CD Cookbook (CD-R, CD-RW)
@ -6,6 +6,7 @@ Content:
- Overwriteable DVD Cookbook (DVD-RAM, DVD+RW, DVD-RW, BD-RE)
- Sequential DVD-R[W] Cookbook
- DVD+R[/DL] Cookbook
- BD-R Cookbook
-------------------------------------------------------------------------------
TAO Multi-Session CD Cookbook
@ -85,7 +86,7 @@ parameters:
BUFE Buffer Underrun protection 0=off, 1=on
Test Write -dummy mode for writing 0=off, 1=on
Write Type Packet/TAO/SAO/RAW 01h = TAO
Multi-session Wether to keep appendable 00b = finalize
Multi-session Whether to keep appendable 00b = finalize
11b = keep appendable
Track Mode Describes frame type 4 for data , 0 for audio
Data Block Type Layout of payload blocks 8 for 2048 byte data blocks
@ -118,19 +119,22 @@ A track must at least contain 300 payload blocks: 4 seconds of audio or
600 KiB of data.
(mmc5r03c.pdf 6.3.3.1.2)
The track has to be closed by 5Bh CLOSE TRACK SESSION Close Function 001b.
Older MMC specifies a valid Logical Track Number FFh to depict the open track.
MMC-5 is quite silent about this. FFh works for my drives.
Up to december 2009 the track was closed by 5Bh CLOSE TRACK SESSION Close
Function 001b. Older MMC specifies a valid Logical Track Number FFh to depict
the open track. MMC-5 is quite silent about this. FFh worked for my drives.
(mmc5r03c.pdf 6.3.3.1.2)
This is omitted since libburn-0.7.4, relying entirely on 35h SYNCHRONIZE CACHE.
First appeared a drive where CLOSE TRACK fails in simulation mode, later
another one produced error replies even with real burning.
After that, a new track may be written beginning with sending the mode page 05h
again. It is not tested wether 05h can be omitted if Track Mode and Data Block
again. It is not tested whether 05h can be omitted if Track Mode and Data Block
Type are the same as with the previous track.
The new track will be added to the session which was opened by the first track.
After the last track of a session, 5Bh CLOSE TRACK SESSION Close Function 010b
with Logical Track Number 0 closes the session. It depends on the Multi-Session
value in mode page 05h wether the disc is finalized or stays appendable.
value in mode page 05h whether the disc is finalized or stays appendable.
(mmc5r03c.pdf 6.3.3.1.3)
@ -201,7 +205,7 @@ for finalized disc.
In libburn the address of the first track in the last session is obtained from
the last session's POINT = A0h and from the track descriptor with the POINT
value matching the PMIN value of the A0h descriptor.
Untested is wether POINT = B0h and 52h READ TRACK INFORMATION are always in
Untested is whether POINT = B0h and 52h READ TRACK INFORMATION are always in
sync. libburn uses the info provided by 52h READ TRACK INFORMATION.
@ -307,7 +311,7 @@ A Write Parameters mode page 05h has to be composed and transmitted via
BUFE Buffer Underrun protection 0=off, 1=on
Test Write -dummy mode for writing 0=off, 1=on
Write Type Packet/TAO/SAO/RAW 02h = SAO
Multi-session Wether to keep appendable 00b = finalize
Multi-session Whether to keep appendable 00b = finalize
11b = keep appendable
Track Mode Describes frame type 0 (is ignored)
Data Block Type Layout of payload blocks 0 (is ignored)
@ -348,7 +352,7 @@ There is no separator between the tracks of a pure mode SAO session.
(If the session was mixed mode, there would be extended Pre-gaps and Post-gaps
between data mode tracks and audio mode tracks.)
(libburn sends its own buffer to the drive at the end of each track but does
not sync the drive's chache. It is unclear wether this separation of tracks
not sync the drive's chache. It is unclear whether this separation of tracks
on the level of 2Ah WRITE is necessary with a pure mode session. It does not
harm in any case and would probably be unavoidable if audio and data tracks
were mixed.)
@ -404,7 +408,7 @@ correctness of Pre-gap and Post-gap would become evident.
Inspired by Andy Polyakov's http://fy.chalmers.se/~appro/linux/DVD+RW/tools ,
backed by reading mmc5r03c.pdf from http://www.t10.org/ftp/t10/drafts/mmc5/
by own experiments with drives NEC ND-4570A, LG GSA-4082B, PHILIPS SPD3300L,
and by BD-RE experiments done by Giulio Orsero on LG BE06LU10.
LG GGW H20L, and by BD-RE experiments done by Giulio Orsero on LG BE06LU10.
For libburnia-project.org by Thomas Schmitt <scdbackup@gmx.net>
@ -432,6 +436,10 @@ The recipes described here are depending on formatting state:
- DVD-RAM and BD-RE formatting
- DVD-RAM and BD-RE speed tuning
Slightly off topic are
- ISO 9660 multi-session emulation on overwriteable media
- ISO 9660 based TOC emulation on overwriteable media
-------------------------------------------------------------------------------
Overwriting in general :
@ -522,7 +530,7 @@ with Close Function 010b despite there is no session open in this scenario.)
-------------------------------------------------------------------------------
Unformatted DVD+RW
Unformatted DVD+RW :
This is the state of previously unused DVD+RW media.
@ -693,9 +701,14 @@ managment. There is no way to increase payload capacity by format 01h.
(mmc5r03c.pdf 6.5.4.2.2.1)
With BD-RE there are three format types : 00h, 30h and 31h.
00h offers the default size format.
00h offers the default size format. This may be the only fast formatting
mode that is offered by the drive.
Feature 0023h tells whether format 31h and certain 30h subtypes are available.
(mmc5r03c.pdf 5.3.13)
30h offers several sizes with defect management. Usually there are three
size to choose: #1: default size, #2: maximum spare area, #3: minimal spare.
sizes given: #1: default size, #2: maximum spare area, #3: minimal spare.
One may demand any spare size between maximum and minimum. There may be quick
certification and full certification. See feature 0023h.
31h offers a single size and disables defect management. This has the side
effect to speed up writing to nominal speed.
(mmc5r03c.pdf 6.5.4.2.15, 6.24.3.3, Table 472)
@ -734,7 +747,7 @@ DVD-RAM and BD-RE tuning :
A special aspect of DVD-RAM and BD-RE is their low speed with write operations,
which usually is only half than the nominal speed of media and drive.
This is blamed to the automatic checkreading which happens ifor managing
This is blamed to the automatic checkreading which happens for managing
eventual defects.
Defect management of BD-RE can be disabled by format type 31h. See above.
@ -745,7 +758,8 @@ The only known way to get full speed from DVD-RAM or BD-RE with enabled defect
management is the use of AAh WRITE12 with Streaming Bit set to 1.
(mmc5r03c.pdf 6.45)
With some DVD-RAM drives this fails if a write buffer is not full 32 kB.
With the tested BD-RE ione has to write write full 64 kB buffers.
With the tested BD-RE one must write full 64 kB buffers, or else writing
might not get into effect at all.
Although it seems not optimal, this is specified not only to disable the
cumbersome checkread but also to ignore known defects and to write data
@ -756,10 +770,83 @@ incorrectable errors.
Caveat:
MMC-5 does not guarantee AAh WRITE12 to work on DVD-RAM or BD-RE at all.
None of the features of profiles 0012h and 0043 promises the existence of
None of the features of profiles 0012h and 0043h promises the existence of
AAh WRITE12.
Nevertheless it worked on all tested drives is proper alignment was observed.
(mmc5r03c.pdf 5.4.13, 6.45)
Nevertheless it worked on all tested drives if proper alignment and block
size was observed.
-------------------------------------------------------------------------------
ISO 9660 multi-session emulation on overwriteable media :
Overwriteable media provide a single overwriteable track which may grow up to
the full media capacity. There is no builtin table-of-content which records
the history of write sessions.
mount -t iso9660 will use sbsector=0 as default.
The term "superblock" shall depict the first 64 KiB after the sbsector address.
ISO 9660 multi-session depends on typical TOC information in two ways:
It needs the superblock address MSC1 of the most recently recorded session and
it needs the Next Writeable Address NWA for which to prepare the adress offset.
The following is learned from growisofs and from ECMA-119:
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-119.pdf
ISO 9660 filesystems provide information about the number of sectors which
is also the lowest unused block address and thus a suitable NWA.
This block address is stored in the Primary Volume Descriptor which is supposed
to be stored in block 16 (eventually relative to MSC1).
The bytes 0 to 5 of a PVD block are
0x01 'C' 'D' '0' '0' '1'
The sector count can then be read from byte 80 to 83
sectors= pvd[80] | (pvd[81] << 8) | (pvd[82] << 16) | (pvd[83] << 24);
(Ecma-119.pdf 8.4)
To support CD, DVD and BD media alike, it is advisable to round the NWA
to the next multiple of 32 (= 64 KiB).
So one can use 0 as MSC1 and prepare a new ISO session for the computed NWA.
After writing the session it is necessary to patch the PVD at LBA 16.
The minimal change would be to update the number of image sectors.
It is stored in both notations LSB and MSB:
for(i= 0; i < 4; i++)
pvd[87 - i]= pvd[80 + i]= (sectors >> (8 * i)) & 0xff;
cdrskin --grow_overwriteable_iso not only patches the sector fields of the
PVD block but also the blocks up to LBA 31 which begin with
0xff 'C' 'D' '0' '0' '1'
libisoburn submits 64 KiB data buffer to libisofs before image generation and
afterwards writes these 64 KiB as new superblock to LBA 0.
-------------------------------------------------------------------------------
ISO 9660 based TOC emulation on overwriteable media :
Above method of multi-session emulation yields a single session image after
each add-on session. No reliable session history can be read because the
sector size of the existing session gets overwritten by the new one.
A TOC with session history is nevertheless desirable with incremental backups
in order to access older backup states by mounting older superblocks at the
start addresses of older sessions.
All usual ISO 9660 formatter programs write a complete superblock to the
start of each session.
With a uniform NWA rounding rule it is possible to compute the address of
superblock N+1 as the NWA after session N. The only problem is N=1
because it gets overwritten by later sessions.
libisoburn preserves the information of session 1 by writing the first session
to LBA 32 rather than LBA 0. Afterwards it writes the overall superblock to
LBA 0 (up to 31).
So with all further add-on sessions the superblock at LBA 0 will enclose the
overall image, while the superblocks of the sessions form a chain beginning
at LBA 32. Each session superblock points to the next one by its sector count
rounded up to 32. The chain end is marked by the overall image size.
This chain gives the start addresses of sessions. The sector count minus start
address gives the size of a particular session. ECMA-119 explains how to
retrieve more info from the PVD (e.g. the volume id).
See also the multi-session example in libisofs/doc/checksums.txt.
-------------------------------------------------------------------------------
@ -853,7 +940,7 @@ Multi-Session by the application.
LS_V Link size valid 1=true
Test Write -dummy mode for writing 0=off, 1=on
Write Type Packet/TAO/SAO/RAW 00h = Incremental (Packet)
Multi-session Wether to keep appendable 00b = finalize
Multi-session Whether to keep appendable 00b = finalize
11b = keep appendable
Track Mode Describes frame type 5 [*1]
Data Block Type Layout of payload blocks 8 [*2]
@ -900,7 +987,7 @@ from the reply of 51h READ DISC INFORMATION requesting Data Type 000b
Multiple tracks are permissible in a single session. After all of them have
been written, 5Bh CLOSE TRACK SESSION Close Function 010b with Logical Track
Number 0 closes the session. It depends on the Multi-Session value in mode
page 05h wether the disc is finalized or stays appendable.
page 05h whether the disc is finalized or stays appendable.
(mmc5r03c.pdf 6.3.3.2.3)
@ -925,7 +1012,7 @@ The mode page 05h to be sent :
LS_V Link size valid 0=false [*3]
Test Write -dummy mode for writing 0=off, 1=on
Write Type Packet/TAO/SAO/RAW 02h = DAO (same code as SAO)
Multi-session Wether to keep appendable 00b = finalize
Multi-session Whether to keep appendable 00b = finalize
Track Mode Describes frame type 5 [*1]
Data Block Type Layout of payload blocks 8 [*2]
Link Size ??? 0 [*3]
@ -1142,7 +1229,7 @@ No mode page 05h is to be sent.
growisofs sends a page but the specs clearly state that one shall not do.
(mmc5r03c.pdf 7.5.3)
It is optional wether a track size is reserved in advance or not. Eventually
It is optional whether a track size is reserved in advance or not. Eventually
this is done by 53h RESERVE TRACK, RMZ=ARSV=0. Reservation size should better
already be aligned to 32 KiB.
(mmc5r03c.pdf 6.31)
@ -1199,3 +1286,118 @@ in http://libburnia-project.org/ticket/13 .
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
BD-R Cookbook
-------------------------------------------------------------------------------
Inspired by reading mmc5r03c.pdf from http://www.t10.org/ftp/t10/drafts/mmc5/
backed by experiments iwith drive LG GGW H20L.
For libburnia-project.org by Thomas Schmitt <scdbackup@gmx.net>
-------------------------------------------------------------------------------
Media type can be recognized by Current Profile from 46h GET CONFIGURATION.
(mmc5r03c.pdf 6.6.2.1)
BD-R 0042h
There are two basic recording modes defined: Sequential Recording Mode SRM and
Random Recording Mode RRM. The latter is optional and for now not topic of this
text.
(mmc5r03c.pdf 4.5.3.5)
- SRM Formatting
- Writing a session in SRM-POW
(- Pseudo-OverWrite SRM+POW)
-------------------------------------------------------------------------------
SRM Formatting:
Despite being write-once media BD-R can optionally carry some formatting.
SRM has a disc structure model with tracks and sessions.
Several tracks may be open at the same time, each having its own NWA.
(mmc5r03c.pdf 4.5.3.5.2.2)
This structure is formatted onto blank media automatically as soon as the
first serious write attempt occurs.
(mmc5r03c.pdf 4.5.3.5)
Before such a write attempt, blank media may be explicitely formatted with
spares, which provide defect management.
(mmc5r03c.pdf 4.5.3.5.3)
Tracks get created from other tracks via RESERVE TRACK splitting.
(mmc5r03c.pdf 4.5.3.5.2.5)
On top of defect management there may be Pseudo-OverWrite SRM+POW, a costly
way to write several times to the same LBA. See below.
Fully sequential states are called SRM-POW.
(mmc5r03c.pdf 4.5.3.5.4)
Explicite formatting is done by 04h FORMAT UNIT. Its data payload consists
of a Format List Header and a Format Descriptor. It is advisable to set
the Immed bit and the FOV bit in header byte number 1. The descriptor should
be a copy of a descriptor from 23h READ FORMAT CAPACITIES but the size may be
adjusted within a certain range.
(mmc5r03c.pdf 6.5, 6.5.3.2, 6.5.3.3)
Format type 00h creates SRM layouts with a default number of spares (or
eventually RRM) chosen by the format sub-type:
00b = SRM with support for POW
01b = SRM without POW (but with some spares for defect management)
10b = (RRM)
(mmc5r03c.pdf 6.5.4.2.1.6)
Format type 32h uses the same sub-types but allows to allocate non-default
amounts of spares. Similar to BD-RE format 31h, three format descriptors are
offered: #1: default size, #2: maximum spare area, #3: minimal spare.
The size may be chosen within that range.
The sense behind the Type Dependent Parameters is obscure
to me. Best will be to set ISA_V and TDMA_V to 0.
(mmc5r03c.pdf 6.5.4.2.1.17)
-------------------------------------------------------------------------------
Writing a session in SRM:
The procedure and constraints for writing BD-R SRM-POW are very similar to
DVD+R. libburn flatly re-uses its DVD+R code except the Close Function for
finalizing a disc.
In short:
If all written sessions are closed, then there is exactly one NWA.
In the beginning there is an empty session and track. A new track can be
written either with pre-announced size (by RESERVE TRACK) or open-end by
simply starting to write to the NWA. When done the track gets closed by
close function 001b. Then either session or disc gets closed depending on
the Close Function used:
- Close Function 010b closes the session and keeps the media appendable
(same as with DVD+R)
- Close Function 110b finalizes the media and makes it read-only.
(differs from libburn DVD+R procedure which uses 101b)
-------------------------------------------------------------------------------
Pseudo-OverWrite POW: (no used yet by libburn)
This enhancement of SRM emulates overwriting of existing data blocks.
(mmc5r03c.pdf 4.5.3.5.4)
POW establishes a virtual vLBA space on top of the real address space rLBA.
All read and write commands deal with vLBA. It seems that track NWAs are
assumed to be identical in vLBA space and in rLBA space.
It is not clear whether one may write to vLBA blocks which are neither written
yet nor at one of the track NWAs. Probably not, or else one could make NWAs run
into vLBAs which are associated with older rLBAs.
Replacing invalidated blocks consumes addresses in rLBA space at the NWA of
some track. I.e. no spares are consumed by POW. Nevertheless it is costly by
a special map called Orphanage. It covers rLBA which have been consumed
by differing vLBAs. It never shrinks and can grow with each write to remapped
addresses.
To avoid heavy Orphanage growth it is advised to write mostly to vLBA which
still coincide with their rLBA. E.g. those addresses which have neither been
written as rLBA nor as vLBA yet. So one should begin the vLBA of new sessions
at the NWA of a sufficiently sized track.
(mmc5r03c.pdf 4.5.3.5.4.2 , 4.5.3.6.9)
-------------------------------------------------------------------------------

View File

@ -38,7 +38,7 @@ PROJECT_NUMBER = @PACKAGE_VERSION@
# If a relative path is entered, it will be relative to the location
# where doxygen was started. If left blank the current directory will be used.
OUTPUT_DIRECTORY =
OUTPUT_DIRECTORY = @abs_top_builddir@
# If the CREATE_SUBDIRS tag is set to YES, then doxygen will create
# 4096 sub-directories (in 2 levels) under the output directory of each output
@ -104,7 +104,7 @@ INLINE_INHERITED_MEMB = NO
# path before files name in the file list and in the header files. If set
# to NO the shortest path that makes the file name unique will be used.
FULL_PATH_NAMES = YES
FULL_PATH_NAMES = NO
# If the FULL_PATH_NAMES tag is set to YES then the STRIP_FROM_PATH tag
# can be used to strip a user-defined part of the path. Stripping is
@ -113,7 +113,7 @@ FULL_PATH_NAMES = YES
# If left blank the directory from which doxygen is run is used as the
# path to strip.
STRIP_FROM_PATH = @top_srcdir@
STRIP_FROM_PATH =
# The STRIP_FROM_INC_PATH tag can be used to strip a user-defined part of
# the path mentioned in the documentation of a class, which tells

1198
doc/mediainfo.txt Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,9 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
/* ts A71019 */
@ -19,15 +23,18 @@
#define Libburn_detach_done_workeR 1
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include "libburn.h"
#include "transport.h"
#include "drive.h"
#include "write.h"
#include "options.h"
#include "file.h"
#include "async.h"
#include "init.h"
#include "file.h"
#include "back_hacks.h"
#include <pthread.h>
@ -36,6 +43,7 @@
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <signal.h>
/*
#include <a ssert.h>
@ -228,6 +236,22 @@ static void *scan_worker_func(struct w_list *w)
return NULL;
}
static void reset_progress(struct burn_drive *d, int sessions, int tracks,
int indices, int sectors, int flag)
{
/* reset the progress indicator */
d->progress.session = 0;
d->progress.sessions = sessions;
d->progress.track = 0;
d->progress.tracks = tracks;
d->progress.index = 0;
d->progress.indices = indices;
d->progress.start_sector = 0;
d->progress.sectors = sectors;
d->progress.sector = 0;
}
int burn_drive_scan(struct burn_drive_info *drives[], unsigned int *n_drives)
{
struct scan_opts o;
@ -297,8 +321,27 @@ drive_is_active:;
static void *erase_worker_func(struct w_list *w)
{
#define Libburn_protect_erase_threaD 1
#ifdef Libburn_protect_erase_threaD
sigset_t sigset, oldset;
/* Protect blank thread from being interrupted by external signals */
sigfillset(&sigset);
sigdelset(&sigset, SIGSEGV);
sigdelset(&sigset, SIGILL);
pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
#endif /* Libburn_protect_erase_threaD */
burn_disc_erase_sync(w->u.erase.drive, w->u.erase.fast);
remove_worker(pthread_self());
#ifdef Libburn_protect_erase_threaD
/* (just in case it would not end with all signals blocked) */
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
#endif /* Libburn_protect_erase_threaD */
return NULL;
}
@ -310,6 +353,7 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
/* a ssert(drive); */
/* a ssert(!SCAN_GOING()); */
/* a ssert(!find_worker(drive)); */
if((drive == NULL)) {
libdax_msgs_submit(libdax_messenger, drive->global_index,
0x00020104,
@ -325,6 +369,9 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
0, 0);
return;
}
reset_progress(drive, 1, 1, 1, 0x10000, 0);
/* A70103 : will be set to 0 by burn_disc_erase_sync() */
drive->cancel = 1;
@ -365,9 +412,28 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
/* ts A61230 */
static void *format_worker_func(struct w_list *w)
{
#define Libburn_protect_format_threaD 1
#ifdef Libburn_protect_format_threaD
sigset_t sigset, oldset;
/* Protect format thread from being interrupted by external signals */
sigfillset(&sigset);
sigdelset(&sigset, SIGSEGV);
sigdelset(&sigset, SIGILL);
pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
#endif /* Libburn_protect_format_threaD */
burn_disc_format_sync(w->u.format.drive, w->u.format.size,
w->u.format.flag);
remove_worker(pthread_self());
#ifdef Libburn_protect_format_threaD
/* (just in case it would not end with all signals blocked) */
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
#endif /* Libburn_protect_format_threaD */
return NULL;
}
@ -376,9 +442,11 @@ static void *format_worker_func(struct w_list *w)
void burn_disc_format(struct burn_drive *drive, off_t size, int flag)
{
struct format_opts o;
int ok = 0;
int ok = 0, ret;
char msg[160];
reset_progress(drive, 1, 1, 1, 0x10000, 0);
if ((SCAN_GOING()) || find_worker(drive) != NULL) {
libdax_msgs_submit(libdax_messenger, drive->global_index,
0x00020102,
@ -409,8 +477,82 @@ void burn_disc_format(struct burn_drive *drive, off_t size, int flag)
flag |= 4; /* format up to maximum size */
} else if (drive->current_profile == 0x12) {
ok = 1; /* DVD-RAM */
} else if (drive->current_profile == 0x41) {
/* BD-R SRM */
ok= 1;
ret = drive->read_format_capacities(drive, 0x00);
if (ret > 0 &&
drive->format_descr_type == BURN_FORMAT_IS_FORMATTED)
ok = 0;
if (drive->status != BURN_DISC_BLANK)
ok = 0;
if (!ok) {
libdax_msgs_submit(libdax_messenger,
drive->global_index, 0x00020162,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"BD-R not unformatted blank any more. Cannot format.",
0, 0);
drive->cancel = 1;
return;
}
if (flag & 32) {
libdax_msgs_submit(libdax_messenger,
drive->global_index, 0x00020163,
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
"Blank BD-R left unformatted for zero spare capacity.",
0, 0);
return;
}
} else if (drive->current_profile == 0x43) {
ok = 1; /* BD-RE */
if ((flag & 32) && !(drive->current_feat23h_byte4 & 8)) {
libdax_msgs_submit(libdax_messenger,
drive->global_index, 0x00020164,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Drive does not format BD-RE without spares.",
0, 0);
drive->cancel = 1;
return;
}
if ((flag & 6) != 6 || (flag & 128)) {
if ((flag & 64) && !(drive->current_feat23h_byte4 & 2)) {
if (drive->current_feat23h_byte4 & 1) {
libdax_msgs_submit(libdax_messenger,
drive->global_index, 0x00020165,
LIBDAX_MSGS_SEV_WARNING,
LIBDAX_MSGS_PRIO_HIGH,
"Drive does not support fast formatting",
0, 0);
flag &= ~64;
} else {
no_non_default_bd_re:;
libdax_msgs_submit(libdax_messenger,
drive->global_index, 0x00020167,
LIBDAX_MSGS_SEV_SORRY,
LIBDAX_MSGS_PRIO_HIGH,
"Drive does not support non-default formatting",
0, 0);
drive->cancel = 1;
return;
}
}
if ((!(flag & 64)) && !(drive->current_feat23h_byte4 & 1)){
if (drive->current_feat23h_byte4 & 2) {
libdax_msgs_submit(libdax_messenger,
drive->global_index, 0x00020166,
LIBDAX_MSGS_SEV_WARNING,
LIBDAX_MSGS_PRIO_HIGH,
"Drive does not support full formatting",
0, 0);
flag |= 64;
} else
goto no_non_default_bd_re;
}
}
}
if (!ok) {
@ -434,8 +576,22 @@ void burn_disc_format(struct burn_drive *drive, off_t size, int flag)
static void *write_disc_worker_func(struct w_list *w)
{
struct burn_drive *d = w->u.write.drive;
char msg[80];
#define Libburn_protect_write_threaD 1
#ifdef Libburn_protect_write_threaD
sigset_t sigset, oldset;
/* Protect write thread from being interrupted by external signals */
sigfillset(&sigset);
sigdelset(&sigset, SIGSEGV);
sigdelset(&sigset, SIGILL);
pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
#endif /* Libburn_protect_write_threaD */
d->thread_pid = getpid();
d->thread_tid = pthread_self();
d->thread_pid_valid= 1;
burn_disc_write_sync(w->u.write.opts, w->u.write.disc);
d->thread_pid_valid= 0;
@ -445,7 +601,19 @@ static void *write_disc_worker_func(struct w_list *w)
*/
burn_write_opts_free(w->u.write.opts);
sprintf(msg, "Write thread on drive %d ended", d->global_index);
libdax_msgs_submit(libdax_messenger, d->global_index, 0x00020178,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
remove_worker(pthread_self());
d->busy = BURN_DRIVE_IDLE;
#ifdef Libburn_protect_write_threaD
/* (just in case it would not end with all signals blocked) */
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
#endif /* Libburn_protect_write_threaD */
return NULL;
}
@ -453,12 +621,15 @@ void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
{
struct write_opts o;
char reasons[BURN_REASONS_LEN+80];
struct burn_drive *d;
d = opts->drive;
/* ts A61006 */
/* a ssert(!SCAN_GOING()); */
/* a ssert(!find_worker(opts->drive)); */
if ((SCAN_GOING()) || find_worker(opts->drive) != NULL) {
libdax_msgs_submit(libdax_messenger, opts->drive->global_index,
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020102,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"A drive operation is still going on (want to write)",
@ -466,15 +637,18 @@ void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
return;
}
reset_progress(d, disc->sessions, disc->session[0]->tracks,
disc->session[0]->track[0]->indices, 0, 0);
/* For the next lines any return indicates failure */
opts->drive->cancel = 1;
d->cancel = 1;
/* ts A70203 : people have been warned in API specs */
if (opts->write_type == BURN_WRITE_NONE)
return;
if (opts->drive->drive_role == 0) {
libdax_msgs_submit(libdax_messenger, opts->drive->global_index,
if (d->drive_role == 0) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020146,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Drive is a virtual placeholder (null-drive)", 0, 0);
@ -482,9 +656,9 @@ void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
}
/* ts A61007 : obsolete Assert in spc_select_write_params() */
if (opts->drive->drive_role == 1 && !opts->drive->mdata->valid) {
if (d->drive_role == 1 && d->mdata->valid <= 0) {
libdax_msgs_submit(libdax_messenger,
opts->drive->global_index, 0x00020113,
d->global_index, 0x00020113,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Drive capabilities not inquired yet", 0, 0);
return;
@ -495,31 +669,67 @@ void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
*/
strcpy(reasons, "Write job parameters are unsuitable:\n");
if (burn_precheck_write(opts, disc, reasons + strlen(reasons), 1)
== BURN_WRITE_NONE) {
<= 0) {
libdax_msgs_submit(libdax_messenger,
opts->drive->global_index, 0x00020139,
d->global_index, 0x00020139,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
reasons, 0, 0);
return;
}
opts->drive->cancel = 0; /* End of the return = failure area */
/* ts A90106 : early catching of unformatted BD-RE */
if (d->current_profile == 0x43)
if (d->read_format_capacities(d, 0x00) > 0 &&
d->format_descr_type != BURN_FORMAT_IS_FORMATTED) {
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x00020168,
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
"Media not properly formatted. Cannot write.",
0, 0);
return;
}
o.drive = opts->drive;
d->cancel = 0; /* End of the return = failure area */
o.drive = d;
o.opts = opts;
o.disc = disc;
opts->refcount++;
add_worker(Burnworker_type_writE, opts->drive,
add_worker(Burnworker_type_writE, d,
(WorkerFunc) write_disc_worker_func, &o);
}
static void *fifo_worker_func(struct w_list *w)
{
int old;
#define Libburn_protect_fifo_threaD 1
#ifdef Libburn_protect_fifo_threaD
sigset_t sigset, oldset;
/* Protect fifo thread from being interrupted by external signals */
sigfillset(&sigset);
sigdelset(&sigset, SIGSEGV);
sigdelset(&sigset, SIGILL);
pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
#endif /* Libburn_protect_fifo_threaD */
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old);
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old);
/* Note: Only burn_fifo_abort() shall cancel the fifo thread */
burn_fifo_source_shoveller(w->u.fifo.source, w->u.fifo.flag);
remove_worker(pthread_self());
#ifdef Libburn_protect_fifo_threaD
/* (just in case it would not end with all signals blocked) */
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
#endif /* Libburn_protect_fifo_threaD */
return NULL;
}
@ -532,7 +742,8 @@ int burn_fifo_start(struct burn_source *source, int flag)
fs->is_started = -1;
/* create and set up ring buffer */;
fs->buf = calloc(fs->chunksize, fs->chunks);
fs->buf = burn_os_alloc_buffer(
((size_t) fs->chunksize) * (size_t) fs->chunks, 0);
if (fs->buf == NULL) {
/* >>> could not start ring buffer */;
return -1;
@ -543,10 +754,32 @@ int burn_fifo_start(struct burn_source *source, int flag)
add_worker(Burnworker_type_fifO, NULL,
(WorkerFunc) fifo_worker_func, &o);
fs->is_started = 1;
return 1;
}
int burn_fifo_abort(struct burn_source_fifo *fs, int flag)
{
int ret;
pthread_t pt;
if (fs->thread_is_valid <= 0 || fs->thread_handle == NULL)
return(2);
#ifdef NIX
libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
"Aborting running burn_source_fifo thread", 0, 0);
#endif /* NIX */
pt= *((pthread_t *) fs->thread_handle);
remove_worker(pt);
ret = pthread_cancel(pt);
return (ret == 0);
}
#ifdef Libburn_has_burn_async_join_alL
/* ts A71019 : never used */

View File

@ -10,5 +10,9 @@ struct burn_write_opts;
/* To be called when the first read() call comes to a fifo */
int burn_fifo_start(struct burn_source *source, int flag);
/* ts A81108 */
/* To abort a running fifo thread before the fifo object gets deleted */
int burn_fifo_abort(struct burn_source_fifo *fs, int flag);
#endif /* BURN__ASYNC_H */

View File

@ -1,4 +1,6 @@
/**
Copyright (c) 2006 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
This file bundles variables which disable changes in libburn which are
not yet completely accepted.

View File

@ -3,13 +3,17 @@
A signal handler which cleans up an application and exits.
Provided under GPL license within GPL projects, BSD license elsewise.
Provided under GPLv2+ license within GPL projects, BSD license elsewise.
*/
/*
cc -g -o cleanup -DCleanup_standalonE cleanup.c
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <sys/types.h>
#include <stdlib.h>
#include <unistd.h>
@ -40,7 +44,8 @@ static int non_signal_list_count= BURN_OS_NON_SIGNAL_COUNT;
#else /* ! Cleanup_has_no_libburn_os_H */
/* Outdated. Linux only. For backward compatibility with pre-libburn-0.2.3 */
/* Outdated. GNU/Linux only.
For backward compatibility with pre-libburn-0.2.3 */
/* Signals to be caught */
static int signal_list[]= {
@ -97,8 +102,8 @@ static int Cleanup_handler_exit(int exit_value, int signum, int flag)
return(2);
}
if(cleanup_exiting) {
fprintf(stderr,"cleanup: ABORT : repeat by pid=%d, signum=%d\n",
getpid(),signum);
fprintf(stderr,"cleanup: ABORT : repeat by pid=%.f, signum=%d\n",
(double) getpid(), signum);
return(0);
}
cleanup_exiting= 1;

View File

@ -3,7 +3,7 @@
A signal handler which cleans up an application and exits.
Provided under GPL license within GPL projects, BSD license elsewise.
Provided under GPLv2+ within GPL projects, BSD license elsewise.
*/
#ifndef Cleanup_includeD

View File

@ -1,5 +1,9 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include "crc.h"
static unsigned short ccitt_table[256] = {
@ -104,6 +108,15 @@ unsigned long crc32_table[256] = {
0x71C0FC00L, 0xE151FD01L, 0xE0E1FE01L, 0x7070FF00L
};
/* Exploration ts B00214 :
ECMA-130, 22.3.6 "CRC field"
Generating polynomial: x^16 + x^12 + x^5 + 1
Also known as CRC-16-CCITT, CRC-CCITT
Use in libburn for raw write modes in sector.c.
There is also disabled code in read.c which would use it.
*/
unsigned short crc_ccitt(unsigned char *q, int len)
{
unsigned short crc = 0;
@ -112,6 +125,20 @@ unsigned short crc_ccitt(unsigned char *q, int len)
crc = ccitt_table[(crc >> 8 ^ *q++) & 0xff] ^ (crc << 8);
return ~crc;
}
/* Exploration ts B00214 :
ECMA-130, 14.3 "EDC field"
"The EDC codeword must be divisible by the check polynomial:
P(x) = (x^16 + x^15 + x^2 + 1) . (x^16 + x^2 + x + 1)
"
>>> Test whether this coincides with CRC-32 IEEE 802.3
x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10
+ x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
Used for raw writing in sector.c
*/
unsigned int crc_32(unsigned char *data, int len)
{
unsigned int crc = 0;

View File

@ -3,7 +3,21 @@
#ifndef BURN__CRC_H
#define BURN__CRC_H
#ifdef Xorriso_standalonE
/* Source module crc.c of yet unclear ancestry is excluded from GNU xorriso */
#ifndef Libburn_no_crc_C
#define Libburn_no_crc_C 1
#endif
#endif
#ifndef Libburn_no_crc_C
unsigned short crc_ccitt(unsigned char *, int len);
unsigned int crc_32(unsigned char *, int len);
#endif /* Libburn_no_crc_C */
#endif /* BURN__CRC_H */

View File

@ -22,6 +22,10 @@
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>

View File

@ -1,5 +1,14 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#ifdef WIN32
#include <windows.h>
#endif

View File

@ -1,9 +1,19 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <sys/types.h>
#include <sys/stat.h>
/* #include <m alloc.h> ts A61013 : not in Linux man 3 malloc */
/* #include <m alloc.h> ts A61013 : not in GNU/Linux man 3 malloc */
#include <stdlib.h>
#include <unistd.h>
@ -40,6 +50,9 @@
/* A70903 : for burn_scsi_setup_drive() */
#include "spc.h"
/* A90815 : for mmc_obtain_profile_name() */
#include "mmc.h"
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
@ -62,6 +75,7 @@ int burn_setup_drive(struct burn_drive *d, char *fname)
d->stdio_fd = -1;
d->status = BURN_DISC_UNREADY;
d->do_stream_recording = 0;
d->stream_recording_start= 0;
return 1;
}
@ -86,6 +100,7 @@ void burn_drive_free_subs(struct burn_drive *d)
if (d->stdio_fd >= 0)
close (d->stdio_fd);
d->stdio_fd = -1;
sg_dispose_drive(d, 0);
}
@ -231,7 +246,7 @@ int burn_drive_inquire_media(struct burn_drive *d)
/* ts A61020 : d->status was set to BURN_DISC_BLANK as pure guess */
/* ts A71128 : run read_disc_info() for any recognizeable profile */
if (d->current_profile > 0 ||
if (d->current_profile > 0 || d->current_is_guessed_profile ||
d->mdata->cdr_write || d->mdata->cdrw_write ||
d->mdata->dvdr_write || d->mdata->dvdram_write) {
@ -365,6 +380,7 @@ struct burn_drive *burn_drive_register(struct burn_drive *d)
d->busy = BURN_DRIVE_IDLE;
d->thread_pid = 0;
d->thread_pid_valid = 0;
memset(&(d->thread_tid), 0, sizeof(d->thread_tid));
d->toc_entries = 0;
d->toc_entry = NULL;
d->disc = NULL;
@ -417,9 +433,8 @@ int burn_drive_unregister(struct burn_drive *d)
struct burn_drive *burn_drive_finish_enum(struct burn_drive *d)
{
struct burn_drive *t;
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
int mmc_function_spy(struct burn_drive *d, char * text);
char msg[BURN_DRIVE_ADR_LEN + 160];
int ret;
d->drive_role = 1; /* MMC drive */
@ -429,13 +444,19 @@ struct burn_drive *burn_drive_finish_enum(struct burn_drive *d)
mmc_function_spy(NULL, "enumerate_common : -------- doing grab");
/* try to get the drive info */
if (t->grab(t)) {
ret = t->grab(t);
if (ret) {
burn_print(2, "getting drive info\n");
t->getcaps(t);
t->unlock(t);
t->released = 1;
} else {
burn_print(2, "unable to grab new located drive\n");
/* ts A90602 */
d->mdata->valid = -1;
sprintf(msg, "Unable to grab scanned drive %s", d->devname);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002016f, LIBDAX_MSGS_SEV_DEBUG,
LIBDAX_MSGS_PRIO_LOW, msg, 0, 0);
burn_drive_unregister(t);
t = NULL;
}
@ -508,6 +529,7 @@ int burn_drive_release_fl(struct burn_drive *d, int flag)
d->unlock(d);
if ((flag & 7) == 1)
d->eject(d);
burn_drive_snooze(d, 0);
d->release(d);
}
@ -520,6 +542,22 @@ int burn_drive_release_fl(struct burn_drive *d, int flag)
}
/* API */
/* ts A90824
@param flag bit0= wake up (else start snoozing)
*/
int burn_drive_snooze(struct burn_drive *d, int flag)
{
if (d->drive_role != 1)
return 0;
if (flag & 1)
d->start_unit(d);
else
d->stop_unit(d);
return 1;
}
/* API */
void burn_drive_release(struct burn_drive *d, int le)
{
@ -588,8 +626,9 @@ void burn_disc_erase_sync(struct burn_drive *d, int fast)
d->idata->product);
d->cancel = 0;
d->busy = BURN_DRIVE_ERASING;
d->erase(d, fast);
#ifdef Libburn_reset_progress_asynC
/* <<< This is now done in async.c */
/* reset the progress */
d->progress.session = 0;
d->progress.sessions = 1;
@ -600,6 +639,11 @@ void burn_disc_erase_sync(struct burn_drive *d, int fast)
d->progress.start_sector = 0;
d->progress.sectors = 0x10000;
d->progress.sector = 0;
#endif /* Libburn_reset_progress_asynC */
d->erase(d, fast);
d->busy = BURN_DRIVE_ERASING;
/* read the initial 0 stage */
while (!d->test_unit_ready(d) && d->get_erase_progress(d) == 0)
sleep(1);
@ -624,8 +668,10 @@ void burn_disc_format_sync(struct burn_drive *d, off_t size, int flag)
int ret, buf_secs, err, i, stages = 1, pbase, pfill, pseudo_sector;
off_t num_bufs;
char msg[80];
struct buffer buf;
struct buffer buf, *buf_mem = d->buffer;
#ifdef Libburn_reset_progress_asynC
/* <<< This is now done in async.c */
/* reset the progress */
d->progress.session = 0;
d->progress.sessions = 1;
@ -636,6 +682,8 @@ void burn_disc_format_sync(struct burn_drive *d, off_t size, int flag)
d->progress.start_sector = 0;
d->progress.sectors = 0x10000;
d->progress.sector = 0;
#endif /* Libburn_reset_progress_asynC */
stages = 1 + ((flag & 1) && size > 1024 * 1024);
d->cancel = 0;
d->busy = BURN_DRIVE_FORMATTING;
@ -706,7 +754,7 @@ void burn_disc_format_sync(struct burn_drive *d, off_t size, int flag)
ex:;
d->progress.sector = 0x10000;
d->busy = BURN_DRIVE_IDLE;
d->buffer = NULL;
d->buffer = buf_mem;
}
@ -772,10 +820,22 @@ int burn_disc_erasable(struct burn_drive *d)
enum burn_drive_status burn_drive_get_status(struct burn_drive *d,
struct burn_progress *p)
{
/* --- Part of asynchronous signal handling --- */
/* This frequently used call may be used to react on messages from
the libburn built-in signal handler.
*/
/* ts B00225 :
If aborting with action 2:
catch control thread after it returned from signal handler.
Let it run burn_abort(4440,...)
*/
burn_init_catch_on_abort(0);
/* ts A70928 : inform control thread of signal in sub-threads */
if (burn_global_abort_level > 0)
if (burn_builtin_triggered_action < 2 && burn_global_abort_level > 0)
burn_global_abort_level++;
if (burn_global_abort_level > 5) {
if (burn_builtin_triggered_action < 2 && burn_global_abort_level > 5) {
if (burn_global_signal_handler == NULL)
kill(getpid(), burn_global_abort_signum);
else
@ -785,6 +845,9 @@ enum burn_drive_status burn_drive_get_status(struct burn_drive *d,
burn_global_abort_level = -1;
}
/* --- End of asynchronous signal handling --- */
if (p != NULL) {
memcpy(p, &(d->progress), sizeof(struct burn_progress));
/* TODO: add mutex */
@ -792,11 +855,27 @@ enum burn_drive_status burn_drive_get_status(struct burn_drive *d,
return d->busy;
}
int burn_drive_set_stream_recording(struct burn_drive *d, int recmode,
int start, int flag)
{
if (recmode == 1)
d->do_stream_recording = 1;
else if (recmode == -1)
d->do_stream_recording = 0;
d->stream_recording_start = start;
return(1);
}
void burn_drive_cancel(struct burn_drive *d)
{
/* ts B00225 : these mutexes are unnecessary because "= 1" is atomar.
pthread_mutex_lock(&d->access_lock);
*/
d->cancel = 1;
/*
pthread_mutex_unlock(&d->access_lock);
*/
}
/* ts A61007 : defunct because unused */
@ -842,7 +921,7 @@ static int drive_getcaps(struct burn_drive *d, struct burn_drive_info *out)
a ssert(d->mdata);
#endif
if (!d->idata->valid || !d->mdata->valid)
if(d->idata->valid <= 0 || d->mdata->valid <= 0)
return 0;
id = (struct burn_scsi_inquiry_data *)d->idata;
@ -868,6 +947,29 @@ static int drive_getcaps(struct burn_drive *d, struct burn_drive_info *out)
out->write_simulate = !!d->mdata->simulate;
out->c2_errors = !!d->mdata->c2_pointers;
out->drive = d;
#ifdef Libburn_dummy_probe_write_modeS
/* ts A91112 */
/* Set default block types. The call d->probe_write_modes() is quite
obtrusive. It may be performed explicitely by new API call
burn_drive_probe_cd_write_modes().
*/
if (out->write_dvdram || out->write_dvdr ||
out->write_cdrw || out->write_cdr) {
out->tao_block_types = d->block_types[BURN_WRITE_TAO] =
BURN_BLOCK_MODE1 | BURN_BLOCK_RAW0;
out->sao_block_types = d->block_types[BURN_WRITE_SAO] =
BURN_BLOCK_SAO;
} else {
out->tao_block_types = d->block_types[BURN_WRITE_TAO] = 0;
out->sao_block_types = d->block_types[BURN_WRITE_SAO] = 0;
}
out->raw_block_types = d->block_types[BURN_WRITE_RAW] = 0;
out->packet_block_types = 0;
#else /* Libburn_dummy_probe_write_modeS */
/* update available block types for burners */
if (out->write_dvdram || out->write_dvdr ||
out->write_cdrw || out->write_cdr)
@ -876,6 +978,30 @@ static int drive_getcaps(struct burn_drive *d, struct burn_drive_info *out)
out->sao_block_types = d->block_types[BURN_WRITE_SAO];
out->raw_block_types = d->block_types[BURN_WRITE_RAW];
out->packet_block_types = d->block_types[BURN_WRITE_PACKET];
#endif /* ! Libburn_dummy_probe_write_modeS */
return 1;
}
/* ts A91112 - B00114 API */
/* Probe available CD write modes and block types.
*/
int burn_drive_probe_cd_write_modes(struct burn_drive_info *dinfo)
{
struct burn_drive *d = dinfo->drive;
if (d == NULL)
return 0;
if (dinfo->write_dvdram || dinfo->write_dvdr ||
dinfo->write_cdrw || dinfo->write_cdr)
d->probe_write_modes(d);
dinfo->tao_block_types = d->block_types[BURN_WRITE_TAO];
dinfo->sao_block_types = d->block_types[BURN_WRITE_SAO];
dinfo->raw_block_types = d->block_types[BURN_WRITE_RAW];
dinfo->packet_block_types = d->block_types[BURN_WRITE_PACKET];
return 1;
}
@ -908,7 +1034,7 @@ int burn_drive_scan_sync(struct burn_drive_info *drives[],
*/
unsigned char scanned[32];
unsigned count = 0;
int i;
int i, ret;
/* ts A61007 : moved up to burn_drive_scan() */
/* a ssert(burn_running); */
@ -965,13 +1091,22 @@ int burn_drive_scan_sync(struct burn_drive_info *drives[],
if (drive_array[i].global_index < 0)
continue; /* invalid device */
while (!drive_getcaps(&drive_array[i],
&(*drives)[*n_drives])) {
/* ts A90602 : This old loop is not plausible. See A70907.
while (!drive_getcaps(&drive_array[i],
&(*drives)[*n_drives])) {
sleep(1);
}
(*n_drives)++;
}
*/
/* ts A90602 : A single call shall do (rather than a loop) */
ret = drive_getcaps(&drive_array[i], &(*drives)[*n_drives]);
if (ret > 0)
(*n_drives)++;
scanned[i / 8] |= 1 << (i % 8);
}
if (*drives != NULL && *n_drives == 0) {
free ((char *) *drives);
*drives = NULL;
}
return(1);
}
@ -1127,14 +1262,14 @@ void burn_sectors_to_msf(int sectors, int *m, int *s, int *f)
int burn_drive_get_read_speed(struct burn_drive *d)
{
if(!d->mdata->valid)
if(d->mdata->valid <= 0)
return 0;
return d->mdata->max_read_speed;
}
int burn_drive_get_write_speed(struct burn_drive *d)
{
if(!d->mdata->valid)
if(d->mdata->valid <= 0)
return 0;
return d->mdata->max_write_speed;
}
@ -1142,7 +1277,7 @@ int burn_drive_get_write_speed(struct burn_drive *d)
/* ts A61021 : New API function */
int burn_drive_get_min_write_speed(struct burn_drive *d)
{
if(!d->mdata->valid)
if(d->mdata->valid <= 0)
return 0;
return d->mdata->min_write_speed;
}
@ -1227,8 +1362,10 @@ int burn_drive__fd_from_special_adr(char *adr)
int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname)
{
int ret = -1, fd = -1, role = 0;
int is_block_dev = 0;
/* divided by 512 it needs to fit into a signed long integer */
off_t size = ((off_t) (512 * 1024 * 1024 - 1) * (off_t) 2048);
off_t read_size = -1;
struct burn_drive *d= NULL, *regd_d;
struct stat stbuf;
@ -1241,8 +1378,19 @@ int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname)
ret = fstat(fd, &stbuf);
else
ret = stat(fname, &stbuf);
if (ret == -1 || S_ISBLK(stbuf.st_mode) ||
S_ISREG(stbuf.st_mode)) {
if (ret != -1) {
is_block_dev = burn_os_is_2k_seekrw(fname, 0);
if (S_ISREG(stbuf.st_mode))
read_size = stbuf.st_size;
else if (is_block_dev) {
ret = burn_os_stdio_capacity(fname,
&read_size);
if (ret <= 0)
read_size = (off_t) 0x7ffffff0 *
(off_t) 2048;
}
}
if (ret == -1 || is_block_dev || S_ISREG(stbuf.st_mode)) {
ret = burn_os_stdio_capacity(fname, &size);
if (ret == -1) {
libdax_msgs_submit(libdax_messenger, -1,
@ -1299,6 +1447,10 @@ int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname)
d->current_is_supported_profile = 1;
d->block_types[BURN_WRITE_TAO] = BURN_BLOCK_MODE1;
d->block_types[BURN_WRITE_SAO] = BURN_BLOCK_SAO;
if (read_size >= 0)
/* despite its name : last valid address, not size */
d->media_read_capacity =
read_size / 2048 - !(read_size % 2048);
burn_drive_set_media_capacity_remaining(d, size);
/* >>> ? open file for a test ? (>>> beware of "-" = stdin) */;
@ -1454,14 +1606,23 @@ int burn_drive_is_enumerable_adr(char *adr)
#define BURN_DRIVE_MAX_LINK_DEPTH 20
/* ts A60922 ticket 33 */
int burn_drive_resolve_link(char *path, char adr[], int *recursion_count)
/* @param flag bit0= no debug messages
bit1= resolve only links,
do not rely on drive list for resolving via st_rdev
*/
int burn_drive_resolve_link(char *path, char adr[], int *recursion_count,
int flag)
{
int ret;
char link_target[4096], msg[4096+100], link_adr[4096], *adrpt;
struct stat stbuf;
burn_drive_adr_debug_msg("burn_drive_resolve_link( %s )", path);
if (flag & 1)
burn_drive_adr_debug_msg("burn_drive_resolve_link( %s )",
path);
if (*recursion_count >= BURN_DRIVE_MAX_LINK_DEPTH) {
burn_drive_adr_debug_msg(
if (flag & 1)
burn_drive_adr_debug_msg(
"burn_drive_resolve_link aborts because link too deep",
NULL);
return 0;
@ -1469,12 +1630,15 @@ int burn_drive_resolve_link(char *path, char adr[], int *recursion_count)
(*recursion_count)++;
ret = readlink(path, link_target, sizeof(link_target));
if (ret == -1) {
burn_drive_adr_debug_msg("readlink( %s ) returns -1", path);
if (flag & 1)
burn_drive_adr_debug_msg("readlink( %s ) returns -1",
path);
return 0;
}
if (ret >= sizeof(link_target) - 1) {
sprintf(msg,"readlink( %s ) returns %d (too much)", path, ret);
burn_drive_adr_debug_msg(msg, NULL);
if (flag & 1)
burn_drive_adr_debug_msg(msg, NULL);
return -1;
}
link_target[ret] = 0;
@ -1487,10 +1651,25 @@ int burn_drive_resolve_link(char *path, char adr[], int *recursion_count)
} else
adrpt = link_target;
}
ret = burn_drive_convert_fs_adr_sub(adrpt, adr, recursion_count);
sprintf(msg,"burn_drive_convert_fs_adr( %s ) returns %d",
link_target, ret);
burn_drive_adr_debug_msg(msg, NULL);
if (flag & 2) {
/* Link-only recursion */
if (lstat(adrpt, &stbuf) == -1) {
;
} else if((stbuf.st_mode & S_IFMT) == S_IFLNK) {
ret = burn_drive_resolve_link(adrpt, adr,
recursion_count, flag);
} else {
strcpy(adr, adrpt);
}
} else {
/* Link and device number recursion */
ret = burn_drive_convert_fs_adr_sub(adrpt, adr,
recursion_count);
sprintf(msg,"burn_drive_convert_fs_adr( %s ) returns %d",
link_target, ret);
}
if (flag & 1)
burn_drive_adr_debug_msg(msg, NULL);
return ret;
}
@ -1664,7 +1843,7 @@ int burn_drive_convert_fs_adr_sub(char *path, char adr[], int *rec_count)
return 0;
}
if((stbuf.st_mode & S_IFMT) == S_IFLNK) {
ret = burn_drive_resolve_link(path, adr, rec_count);
ret = burn_drive_resolve_link(path, adr, rec_count, 0);
if(ret > 0)
return 1;
burn_drive_adr_debug_msg("link fallback via stat( %s )", path);
@ -1713,23 +1892,29 @@ int burn_abort_pacifier(void *handle, int patience, int elapsed)
}
/** Abort any running drive operation and finish libburn.
@param patience Maximum number of seconds to wait for drives to finish
@param pacifier_func Function to produce appeasing messages. See
burn_abort_pacifier() for an example.
@return 1 ok, all went well
0 had to leave a drive in unclean state
<0 severe error, do no use libburn again
/* ts B00226 : Outsourced backend of burn_abort()
@param flag bit0= do not call burn_finish()
*/
int burn_abort(int patience,
int burn_abort_5(int patience,
int (*pacifier_func)(void *handle, int patience, int elapsed),
void *handle)
void *handle, int elapsed, int flag)
{
int ret, i, occup, still_not_done= 1, pacifier_off= 0, first_round= 1;
unsigned long wait_grain= 100000;
time_t start_time, current_time, pacifier_time, end_time;
#ifndef NIX
time_t stdio_patience = 3;
#endif
/*
fprintf(stderr,
"libburn_EXPERIMENTAL: burn_abort_5(%d,%d)\n", patience, flag);
*/
current_time = start_time = pacifier_time = time(0);
start_time -= elapsed;
end_time = start_time + patience;
/* >>> ts A71002 : are there any threads at work ?
@ -1737,17 +1922,48 @@ int burn_abort(int patience,
change status on their own.
*/
while(current_time-end_time < patience) {
while(current_time < end_time || (patience <= 0 && first_round)) {
still_not_done = 0;
for(i = 0; i < drivetop + 1; i++) {
occup = burn_drive_is_occupied(&(drive_array[i]));
if(occup == -2)
continue;
if(drive_array[i].drive_role != 1) {
#ifdef NIX
/* ts A90302
<<< this causes a race condition with drive
usage and drive disposal.
*/
drive_array[i].busy = BURN_DRIVE_IDLE;
burn_drive_forget(&(drive_array[i]), 1);
} else if(occup <= 10) {
continue;
#else /* NIX */
/* ts A90318
>>> but if a pipe breaks then the drive
never gets idle.
So for now with a short patience timespan
and eventually a deliberate memory leak.
*/
if (current_time - start_time >
stdio_patience) {
drive_array[i].global_index = -1;
continue;
}
#endif /* ! NIX */
}
if(occup <= 10) {
if (drive_array[i].drive_role != 1)
/* occup == -1 comes early */
usleep(1000000);
burn_drive_forget(&(drive_array[i]), 1);
} else if(occup <= 100) {
if(first_round)
@ -1759,7 +1975,7 @@ int burn_abort(int patience,
}
first_round = 0;
if(still_not_done == 0)
if(still_not_done == 0 || patience <= 0)
break;
usleep(wait_grain);
current_time = time(0);
@ -1772,11 +1988,35 @@ int burn_abort(int patience,
pacifier_time = current_time;
}
}
burn_finish();
if (!(flag & 1))
burn_finish();
return(still_not_done == 0);
}
/** Abort any running drive operation and finish libburn.
@param patience Maximum number of seconds to wait for drives to finish
@param pacifier_func Function to produce appeasing messages. See
burn_abort_pacifier() for an example.
@return 1 ok, all went well
0 had to leave a drive in unclean state
<0 severe error, do no use libburn again
*/
int burn_abort(int patience,
int (*pacifier_func)(void *handle, int patience, int elapsed),
void *handle)
{
int ret, flg = 0;
if (patience < 0) {
patience = 0;
flg |= 1;
}
ret = burn_abort_5(patience, pacifier_func, handle, 0, flg);
return ret;
}
/* ts A61020 API function */
int burn_drive_get_start_end_lba(struct burn_drive *d,
int *start_lba, int *end_lba, int flag)
@ -1826,11 +2066,16 @@ int burn_disc_read_atip(struct burn_drive *d)
}
if(d->drive_role != 1)
return 0;
if (d->current_profile == -1 || d->current_is_cd_profile) {
if ((d->current_profile == -1 || d->current_is_cd_profile)
&& (d->mdata->cdrw_write || d->current_profile != 0x08)) {
d->read_atip(d);
/* >>> some control of success would be nice :) */
} else {
/* mmc5r03c.pdf 6.26.3.6.3 : ATIP is undefined for non-CD */;
/* mmc5r03c.pdf 6.26.3.6.3 : ATIP is undefined for non-CD
(and it seems meaningless for non-burners).
ts A90823: Pseudo-CD U3 memory stick stalls with ATIP.
It is !cdrw_write and profile is 0x08.
*/
return 0;
}
return 1;
@ -1938,6 +2183,30 @@ int burn_disc_get_profile(struct burn_drive *d, int *pno, char name[80])
}
/* ts A90815 : New API function */
int burn_drive_get_all_profiles(struct burn_drive *d, int *num_profiles,
int profiles[64], char is_current[64])
{
int i;
*num_profiles = d->num_profiles;
for (i = 0; i < d->num_profiles; i++) {
profiles[i] = (d->all_profiles[i * 4] << 8) |
d->all_profiles[i * 4 + 1];
is_current[i] = d->all_profiles[i * 4 + 2] & 1;
}
return 1;
}
/* ts A90815 : New API function */
int burn_obtain_profile_name(int profile_number, char name[80])
{
strcpy(name, mmc_obtain_profile_name(profile_number));
return(name[0] != 0);
}
/* ts A61223 : New API function */
int burn_drive_wrote_well(struct burn_drive *d)
{
@ -2037,7 +2306,7 @@ int burn_drive_get_speedlist(struct burn_drive *d,
struct burn_speed_descriptor *sd, *csd = NULL;
(*speed_list) = NULL;
if(!d->mdata->valid)
if(d->mdata->valid <= 0)
return 0;
for (sd = d->mdata->speed_descriptors; sd != NULL; sd = sd->next) {
ret = burn_speed_descriptor_new(&csd, NULL, csd, 0);
@ -2062,7 +2331,7 @@ int burn_drive_get_best_speed(struct burn_drive *d, int speed_goal,
if (speed_goal < 0)
best_speed = 2000000000;
*best_descr = NULL;
if(!d->mdata->valid)
if(d->mdata->valid <= 0)
return 0;
for (sd = d->mdata->speed_descriptors; sd != NULL; sd = sd->next) {
if (flag & 1)
@ -2246,8 +2515,9 @@ int burn_disc_get_multi_caps(struct burn_drive *d, enum burn_write_types wt,
o->might_do_sao = 4;
o->might_do_tao = 2;
o->advised_write_mode = BURN_WRITE_TAO;
} else if (d->current_profile == 0x1b || d->current_profile == 0x2b) {
/* DVD+R , DVD+R/DL */
} else if (d->current_profile == 0x1b || d->current_profile == 0x2b ||
d->current_profile == 0x41) {
/* DVD+R , DVD+R/DL , BD-R SRM */
o->multi_session = o->multi_track = 1;
o->might_do_tao = 2;
o->might_do_sao = 1;
@ -2441,6 +2711,9 @@ int burn_drive_equals_adr(struct burn_drive *d1, char *adr2_in, int role2)
if (S_ISBLK(stbuf1.st_mode) && S_ISBLK(stbuf2.st_mode) &&
stbuf1.st_rdev == stbuf2.st_rdev)
return 1; /* same major,minor device number */
if (S_ISCHR(stbuf1.st_mode) && S_ISCHR(stbuf2.st_mode) &&
stbuf1.st_rdev == stbuf2.st_rdev)
return 1; /* same major,minor device number */
/* Are both filesystem objects related to the same MMC drive */
if (conv_ret2 <= 0)
@ -2477,7 +2750,8 @@ int burn_drive_equals_adr(struct burn_drive *d1, char *adr2_in, int role2)
}
int burn_drive_find_by_thread_pid(struct burn_drive **d, pid_t pid)
int burn_drive_find_by_thread_pid(struct burn_drive **d, pid_t pid,
pthread_t tid)
{
int i;
@ -2489,7 +2763,8 @@ int burn_drive_find_by_thread_pid(struct burn_drive **d, pid_t pid)
*/
if (drive_array[i].thread_pid_valid &&
drive_array[i].thread_pid == pid) {
drive_array[i].thread_pid == pid &&
pthread_equal(drive_array[i].thread_tid, tid)) {
*d = &(drive_array[i]);
return 1;
}
@ -2506,3 +2781,61 @@ int burn_drive_set_media_capacity_remaining(struct burn_drive *d, off_t value)
return 1;
}
/* ts A81215 : API */
int burn_get_read_capacity(struct burn_drive *d, int *capacity, int flag)
{
*capacity = d->media_read_capacity + 1;
return (d->media_read_capacity != 0x7fffffff);
}
/* ts A90903 : API */
int burn_disc_get_media_id(struct burn_drive *d,
char **product_id, char **media_code1, char **media_code2,
char **book_type, int flag)
{
int ret;
*product_id = *media_code1 = *media_code2 = *book_type = NULL;
if (burn_drive_get_drive_role(d) != 1)
return 0;
ret = mmc_get_media_product_id(d,
product_id, media_code1, media_code2, book_type,
flag & 1);
return ret;
}
/* ts A90909 : API */
/**
@param valid Replies bits which indicate the validity of other reply
parameters or the state of certain CD info bits:
bit0= disc_type valid
bit1= disc_id valid
bit2= bar_code valid
bit3= disc_app_code valid
bit4= Disc is unrestricted (URU bit)
bit5= Disc is nominally erasable (Erasable bit)
This will be set with overwriteable media which
libburn normally considers to be unerasable blank.
*/
int burn_disc_get_cd_info(struct burn_drive *d, char disc_type[80],
unsigned int *disc_id, char bar_code[9], int *app_code,
int *valid)
{
if (d->disc_type == 0x00) {
strcpy(disc_type, "CD-DA or CD-ROM");
} else if (d->disc_type == 0x10) {
strcpy(disc_type, "CD-I");
} else if (d->disc_type == 0x20) {
strcpy(disc_type, "CD-ROM XA");
} else {
strcpy(disc_type, "undefined");
}
*disc_id = d->disc_id;
memcpy(bar_code, d->disc_bar_code, 8);
bar_code[9]= 0;
*app_code = d->disc_app_code;
*valid = d->disc_info_valid;
return 1;
}

View File

@ -1,5 +1,11 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifndef __DRIVE
#define __DRIVE
@ -121,8 +127,9 @@ int burn_disc_get_write_mode_demands(struct burn_disc *disc,
int burn_drive__fd_from_special_adr(char *adr);
/* ts A70929 : Find the drive which is being worked on by pid */
int burn_drive_find_by_thread_pid(struct burn_drive **d, pid_t pid);
/* ts A70929 : Find the drive which is being worked on by pid , tid */
int burn_drive_find_by_thread_pid(struct burn_drive **d, pid_t pid,
pthread_t tid);
/* ts A51221 - A80731 : Whitelist inquiry functions */
@ -135,4 +142,12 @@ char *burn_drive_whitelist_item(int idx, int flag);
int burn_drive_is_listed(char *path, struct burn_drive **found, int flag);
/* ts B00226 : Outsourced backend of burn_abort()
@param elapsed to be subtracted from start time
@param flag bit0= do not shutdown the library
*/
int burn_abort_5(int patience,
int (*pacifier_func)(void *handle, int patience, int elapsed),
void *handle, int elapsed, int flag);
#endif /* __DRIVE */

855
libburn/ecma130ab.c Normal file
View File

@ -0,0 +1,855 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
/* ts A91016 : libburn/ecma130ab.c is the replacement for old libburn/lec.c
Copyright 2009, Thomas Schmitt <scdbackup@gmx.net>, libburnia-project.org
Provided under GPL version 2 or later.
This code module implements the production of RSPC parity bytes (P- and Q-
parity) and the scrambling of raw CD-ROM sectors as specified in ECMA-130:
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-130.pdf
The following statements about Galois Fields have been learned mostly from
http://www.cs.utk.edu/~plank/plank/papers/CS-96-332.pdf
by James S. Plank after an e-mail exchange with Norbert Preining.
The output has been compared with the output of the old code of libburn
which was labeled "borrowed HEAVILY from cdrdao" and claimed by Joerg
Schilling to stem from code by Heiko Eissfeldt.
-------------------------------------------------------------------------
Note: In this text, "^" denotes exponentiation and not the binary exor
operation. Confusingly in the C code "^" is said exor.
Note: This is not C1, C2 which is rather mentioned in ECMA-130 Annex C and
always performed inside the drive.
-------------------------------------------------------------------------
RSPC resp. P- and Q-Parity
ECMA-130 Annex A prescribes to compute the parity bytes for P-columns and
Q-diagonals by RSPC based on a Galois Field GF(2^8) with enumerating
polynomials x^8+x^4+x^3+x^2+1 (i.e. 0x11d) and x^1 (i.e. 0x02).
Bytes 12 to 2075 of a audio-sized sector get ordered in two byte words
as 24 rows and 43 columns. Then this matrix is split into a LSB matrix
and a MSB matrix of the same layout. Parity bytes are to be computed
from these 8-bit values.
2 P-bytes cover each column of 24 bytes. They get appended to the matrix
as rows 24 and 25.
2 Q-bytes cover each the 26 diagonals of the extended matrix.
Both parity byte pairs have to be computed so that extended rows or
diagonals match this linear equation:
H x V = (0,0)
H is a 2-row matrix of size n matching the length of the V ectors
[ 1 1 ... 1 1 ]
[ x^(n-1) x^(n-2) x^1 1 ]
Vp represents a P-row. It is a byte vector consisting of row bytes at
position 0 to 23 and the two parity bytes which shall be determined
at position 24 and 25. So Hp has 26 columns.
Vq represents a Q-diagonal. It is a byte vector consisting of diagonal
bytes at position 0 to 42 and the two parity bytes at position 43 and 44.
So Hq has 45 columns. The Q-diagonals cover P-parity bytes.
By applying some high school algebra one gets the parity bytes b0, b1 of
vector V = (n_payload_bytes, b0 , b1) as
b0 = ( H[n] * SUM(n_payload_bytes) - H[0..(n-1)] x n_payload_bytes )
/ (H[n+1] - H[n])
b1 = - SUM(n_payload_bytes) - b0
H[i] is the i-the element of the second row of matrix H. E.g. H[0] = x^(n-1)
The result has to be computed by Galois field arithmetics. See below.
The P-parity bytes of each column get reunited as LSB and MSB of two words.
word1 gets written to positions 1032 to 1074, word0 to 1075 to 1117.
The Q-parity bytes of each diagonal get reunited too. word1 goes to 1118
to 1143, word0 to 1144 to 1169.
>>> I do not read this swap of word1 and word0 from ECMA-130 Annex A.
>>> But the new output matches the old output only if it is done that way.
>>> See correctness reservation below.
Algebra on Galois fields is the same as on Rational Numbers.
But arithmetics is defined by operations on polynomials rather than the
usual integer arithmetics on binary numbers.
Addition and subtraction are identical with the binary exor operator.
Multiplication and division would demand polynomial division, e.g. by the
euclidian algorithm. The computing path over logarithms and powers follows
algebra and allows to reduce the arithmetic task to table lookups, additions
modulo 255, and exor operations. Note that the logarithms are natural
numbers, not polynomials. They get added or subtracted by the usual addition
(not by exor) and their polynomial power depends on their value modulo 255.
Needed are a logarithm table and a power table (or inverse logarithm table)
for Galois Field GF(2^8) which will serve to perform the peculiar
multiplication and division operation of Galois fields.
The power table is simply an enumeration of x^n accorting to
GF-multiplication. It also serves as second line of matrix H for the parity
equations:
Hp[i] = gfpow[25-i] , i out of {0,..,25}
Hq[i] = gfpow[44-i] , i out of {0,..,44}
The logarithm table is the inverse permutation of the power table.
Some simplifications apply to the implementation:
In the world of Galois fields there is no difference between - and +.
The term (H[n+1] - H[n]) is constant: 3.
-------------------------------------------------------------------------
Scrambling
ECMA-130 Annex B prescribes to exor the byte stream of an audio-sized sector
with a sequence of pseudo random bytes. It mentions polynomial x^15+x+1 and
a 15-bit register.
It shows a diagram of a Feedback Shift Register with 16 bit boxes, though.
Comparing this with explanations in
http://www.newwaveinstruments.com/resources/articles/m_sequence_linear_feedback_shift_register_lfsr.htm
one can recognize the diagram as a Fibonacci Implementation. But there seems
really to be one bit box too many.
The difference of both lengths is expressed in function next_bit() by
the constants 0x3fff,0x4000 for 15 bit versus 0x7fff,0x8000 for 16 bits.
Comparing the output of both alternatives with the old scrambler output
lets 15 bit win for now.
So the prescription is to start with 15 bit value 1, to use the lowest bit
as output, to shift the bits down by one, to exor the output bit with the
next lowest bit, and to put that exor result into bit 14 of the register.
-------------------------------------------------------------------------
Correctness Reservation
In both cases, parity and scrambling, the goal for now is to replicate the
output of the dismissed old lec.c by output which is based on published
specs and own implementation code. Whether they comply to ECMA-130 is a
different question which can only be answered by real test cases for
raw CD recording.
Of course this implementation will be corrected so that it really complies
to ECMA-130 as soon as evidence emerges that it does not yet.
*/
/* ------------------------------------------------------------------------- */
/* Power and logarithm tables for GF(2^8), parity matrices for ECMA-130.
Generated by burn_rspc_setup_tables() and burn_rspc_print_tables().
The highest possible sum of gflog[] values is is 508. So the table gfpow[]
with period 255 was manually unrolled to 509 elements to avoid one modulo
255 operation in burn_rspc_mult().
Proposed by D. Hugh Redelmeier.
*/
static unsigned char gfpow[509] = {
1, 2, 4, 8, 16, 32, 64, 128, 29, 58,
116, 232, 205, 135, 19, 38, 76, 152, 45, 90,
180, 117, 234, 201, 143, 3, 6, 12, 24, 48,
96, 192, 157, 39, 78, 156, 37, 74, 148, 53,
106, 212, 181, 119, 238, 193, 159, 35, 70, 140,
5, 10, 20, 40, 80, 160, 93, 186, 105, 210,
185, 111, 222, 161, 95, 190, 97, 194, 153, 47,
94, 188, 101, 202, 137, 15, 30, 60, 120, 240,
253, 231, 211, 187, 107, 214, 177, 127, 254, 225,
223, 163, 91, 182, 113, 226, 217, 175, 67, 134,
17, 34, 68, 136, 13, 26, 52, 104, 208, 189,
103, 206, 129, 31, 62, 124, 248, 237, 199, 147,
59, 118, 236, 197, 151, 51, 102, 204, 133, 23,
46, 92, 184, 109, 218, 169, 79, 158, 33, 66,
132, 21, 42, 84, 168, 77, 154, 41, 82, 164,
85, 170, 73, 146, 57, 114, 228, 213, 183, 115,
230, 209, 191, 99, 198, 145, 63, 126, 252, 229,
215, 179, 123, 246, 241, 255, 227, 219, 171, 75,
150, 49, 98, 196, 149, 55, 110, 220, 165, 87,
174, 65, 130, 25, 50, 100, 200, 141, 7, 14,
28, 56, 112, 224, 221, 167, 83, 166, 81, 162,
89, 178, 121, 242, 249, 239, 195, 155, 43, 86,
172, 69, 138, 9, 18, 36, 72, 144, 61, 122,
244, 245, 247, 243, 251, 235, 203, 139, 11, 22,
44, 88, 176, 125, 250, 233, 207, 131, 27, 54,
108, 216, 173, 71, 142,
1, 2, 4, 8, 16, 32, 64, 128, 29, 58,
116, 232, 205, 135, 19, 38, 76, 152, 45, 90,
180, 117, 234, 201, 143, 3, 6, 12, 24, 48,
96, 192, 157, 39, 78, 156, 37, 74, 148, 53,
106, 212, 181, 119, 238, 193, 159, 35, 70, 140,
5, 10, 20, 40, 80, 160, 93, 186, 105, 210,
185, 111, 222, 161, 95, 190, 97, 194, 153, 47,
94, 188, 101, 202, 137, 15, 30, 60, 120, 240,
253, 231, 211, 187, 107, 214, 177, 127, 254, 225,
223, 163, 91, 182, 113, 226, 217, 175, 67, 134,
17, 34, 68, 136, 13, 26, 52, 104, 208, 189,
103, 206, 129, 31, 62, 124, 248, 237, 199, 147,
59, 118, 236, 197, 151, 51, 102, 204, 133, 23,
46, 92, 184, 109, 218, 169, 79, 158, 33, 66,
132, 21, 42, 84, 168, 77, 154, 41, 82, 164,
85, 170, 73, 146, 57, 114, 228, 213, 183, 115,
230, 209, 191, 99, 198, 145, 63, 126, 252, 229,
215, 179, 123, 246, 241, 255, 227, 219, 171, 75,
150, 49, 98, 196, 149, 55, 110, 220, 165, 87,
174, 65, 130, 25, 50, 100, 200, 141, 7, 14,
28, 56, 112, 224, 221, 167, 83, 166, 81, 162,
89, 178, 121, 242, 249, 239, 195, 155, 43, 86,
172, 69, 138, 9, 18, 36, 72, 144, 61, 122,
244, 245, 247, 243, 251, 235, 203, 139, 11, 22,
44, 88, 176, 125, 250, 233, 207, 131, 27, 54,
108, 216, 173, 71,
};
static unsigned char gflog[256] = {
0, 0, 1, 25, 2, 50, 26, 198, 3, 223,
51, 238, 27, 104, 199, 75, 4, 100, 224, 14,
52, 141, 239, 129, 28, 193, 105, 248, 200, 8,
76, 113, 5, 138, 101, 47, 225, 36, 15, 33,
53, 147, 142, 218, 240, 18, 130, 69, 29, 181,
194, 125, 106, 39, 249, 185, 201, 154, 9, 120,
77, 228, 114, 166, 6, 191, 139, 98, 102, 221,
48, 253, 226, 152, 37, 179, 16, 145, 34, 136,
54, 208, 148, 206, 143, 150, 219, 189, 241, 210,
19, 92, 131, 56, 70, 64, 30, 66, 182, 163,
195, 72, 126, 110, 107, 58, 40, 84, 250, 133,
186, 61, 202, 94, 155, 159, 10, 21, 121, 43,
78, 212, 229, 172, 115, 243, 167, 87, 7, 112,
192, 247, 140, 128, 99, 13, 103, 74, 222, 237,
49, 197, 254, 24, 227, 165, 153, 119, 38, 184,
180, 124, 17, 68, 146, 217, 35, 32, 137, 46,
55, 63, 209, 91, 149, 188, 207, 205, 144, 135,
151, 178, 220, 252, 190, 97, 242, 86, 211, 171,
20, 42, 93, 158, 132, 60, 57, 83, 71, 109,
65, 162, 31, 45, 67, 216, 183, 123, 164, 118,
196, 23, 73, 236, 127, 12, 111, 246, 108, 161,
59, 82, 41, 157, 85, 170, 251, 96, 134, 177,
187, 204, 62, 90, 203, 89, 95, 176, 156, 169,
160, 81, 11, 245, 22, 235, 122, 117, 44, 215,
79, 174, 213, 233, 230, 231, 173, 232, 116, 214,
244, 234, 168, 80, 88, 175
};
#define Libburn_use_h_matriceS 1
#ifdef Libburn_use_h_matriceS
/* On my AMD 2x64 bit 3000 MHz processor h[i] costs about 7 % more time
than using gfpow[25-i] resp. gfpow[44-1]. I blame this on the more
condensed data representation which slightly increases the rate of cache
hits.
Nevertheless this effect is very likely depending on the exact cache
size and architecture. In general, using h[] saves more than 8000
subtractions per sector.
*/
/* Parity matrices H as prescribed by ECMA-130 Annex A.
Actually just reverted order start pieces of gfpow[].
*/
static unsigned char h26[26] = {
3, 143, 201, 234, 117, 180, 90, 45, 152, 76,
38, 19, 135, 205, 232, 116, 58, 29, 128, 64,
32, 16, 8, 4, 2, 1,
};
static unsigned char h45[45] = {
238, 119, 181, 212, 106, 53, 148, 74, 37, 156,
78, 39, 157, 192, 96, 48, 24, 12, 6, 3,
143, 201, 234, 117, 180, 90, 45, 152, 76, 38,
19, 135, 205, 232, 116, 58, 29, 128, 64, 32,
16, 8, 4, 2, 1,
};
#endif /* Libburn_use_h_matriceS */
/* Pseudo-random bytes which of course are exactly the same as with the
previously used code.
Generated by function print_ecma_130_scrambler().
*/
static unsigned char ecma_130_annex_b[2340] = {
1, 128, 0, 96, 0, 40, 0, 30, 128, 8,
96, 6, 168, 2, 254, 129, 128, 96, 96, 40,
40, 30, 158, 136, 104, 102, 174, 170, 252, 127,
1, 224, 0, 72, 0, 54, 128, 22, 224, 14,
200, 4, 86, 131, 126, 225, 224, 72, 72, 54,
182, 150, 246, 238, 198, 204, 82, 213, 253, 159,
1, 168, 0, 126, 128, 32, 96, 24, 40, 10,
158, 135, 40, 98, 158, 169, 168, 126, 254, 160,
64, 120, 48, 34, 148, 25, 175, 74, 252, 55,
1, 214, 128, 94, 224, 56, 72, 18, 182, 141,
182, 229, 182, 203, 54, 215, 86, 222, 190, 216,
112, 90, 164, 59, 59, 83, 83, 125, 253, 225,
129, 136, 96, 102, 168, 42, 254, 159, 0, 104,
0, 46, 128, 28, 96, 9, 232, 6, 206, 130,
212, 97, 159, 104, 104, 46, 174, 156, 124, 105,
225, 238, 200, 76, 86, 181, 254, 247, 0, 70,
128, 50, 224, 21, 136, 15, 38, 132, 26, 227,
75, 9, 247, 70, 198, 178, 210, 245, 157, 135,
41, 162, 158, 249, 168, 66, 254, 177, 128, 116,
96, 39, 104, 26, 174, 139, 60, 103, 81, 234,
188, 79, 49, 244, 20, 71, 79, 114, 180, 37,
183, 91, 54, 187, 86, 243, 126, 197, 224, 83,
8, 61, 198, 145, 146, 236, 109, 141, 237, 165,
141, 187, 37, 179, 91, 53, 251, 87, 3, 126,
129, 224, 96, 72, 40, 54, 158, 150, 232, 110,
206, 172, 84, 125, 255, 97, 128, 40, 96, 30,
168, 8, 126, 134, 160, 98, 248, 41, 130, 158,
225, 168, 72, 126, 182, 160, 118, 248, 38, 194,
154, 209, 171, 28, 127, 73, 224, 54, 200, 22,
214, 142, 222, 228, 88, 75, 122, 183, 99, 54,
169, 214, 254, 222, 192, 88, 80, 58, 188, 19,
49, 205, 212, 85, 159, 127, 40, 32, 30, 152,
8, 106, 134, 175, 34, 252, 25, 129, 202, 224,
87, 8, 62, 134, 144, 98, 236, 41, 141, 222,
229, 152, 75, 42, 183, 95, 54, 184, 22, 242,
142, 197, 164, 83, 59, 125, 211, 97, 157, 232,
105, 142, 174, 228, 124, 75, 97, 247, 104, 70,
174, 178, 252, 117, 129, 231, 32, 74, 152, 55,
42, 150, 159, 46, 232, 28, 78, 137, 244, 102,
199, 106, 210, 175, 29, 188, 9, 177, 198, 244,
82, 199, 125, 146, 161, 173, 184, 125, 178, 161,
181, 184, 119, 50, 166, 149, 186, 239, 51, 12,
21, 197, 207, 19, 20, 13, 207, 69, 148, 51,
47, 85, 220, 63, 25, 208, 10, 220, 7, 25,
194, 138, 209, 167, 28, 122, 137, 227, 38, 201,
218, 214, 219, 30, 219, 72, 91, 118, 187, 102,
243, 106, 197, 239, 19, 12, 13, 197, 197, 147,
19, 45, 205, 221, 149, 153, 175, 42, 252, 31,
1, 200, 0, 86, 128, 62, 224, 16, 72, 12,
54, 133, 214, 227, 30, 201, 200, 86, 214, 190,
222, 240, 88, 68, 58, 179, 83, 53, 253, 215,
1, 158, 128, 104, 96, 46, 168, 28, 126, 137,
224, 102, 200, 42, 214, 159, 30, 232, 8, 78,
134, 180, 98, 247, 105, 134, 174, 226, 252, 73,
129, 246, 224, 70, 200, 50, 214, 149, 158, 239,
40, 76, 30, 181, 200, 119, 22, 166, 142, 250,
228, 67, 11, 113, 199, 100, 82, 171, 125, 191,
97, 176, 40, 116, 30, 167, 72, 122, 182, 163,
54, 249, 214, 194, 222, 209, 152, 92, 106, 185,
239, 50, 204, 21, 149, 207, 47, 20, 28, 15,
73, 196, 54, 211, 86, 221, 254, 217, 128, 90,
224, 59, 8, 19, 70, 141, 242, 229, 133, 139,
35, 39, 89, 218, 186, 219, 51, 27, 85, 203,
127, 23, 96, 14, 168, 4, 126, 131, 96, 97,
232, 40, 78, 158, 180, 104, 119, 110, 166, 172,
122, 253, 227, 1, 137, 192, 102, 208, 42, 220,
31, 25, 200, 10, 214, 135, 30, 226, 136, 73,
166, 182, 250, 246, 195, 6, 209, 194, 220, 81,
153, 252, 106, 193, 239, 16, 76, 12, 53, 197,
215, 19, 30, 141, 200, 101, 150, 171, 46, 255,
92, 64, 57, 240, 18, 196, 13, 147, 69, 173,
243, 61, 133, 209, 163, 28, 121, 201, 226, 214,
201, 158, 214, 232, 94, 206, 184, 84, 114, 191,
101, 176, 43, 52, 31, 87, 72, 62, 182, 144,
118, 236, 38, 205, 218, 213, 155, 31, 43, 72,
31, 118, 136, 38, 230, 154, 202, 235, 23, 15,
78, 132, 52, 99, 87, 105, 254, 174, 192, 124,
80, 33, 252, 24, 65, 202, 176, 87, 52, 62,
151, 80, 110, 188, 44, 113, 221, 228, 89, 139,
122, 231, 99, 10, 169, 199, 62, 210, 144, 93,
172, 57, 189, 210, 241, 157, 132, 105, 163, 110,
249, 236, 66, 205, 241, 149, 132, 111, 35, 108,
25, 237, 202, 205, 151, 21, 174, 143, 60, 100,
17, 235, 76, 79, 117, 244, 39, 7, 90, 130,
187, 33, 179, 88, 117, 250, 167, 3, 58, 129,
211, 32, 93, 216, 57, 154, 146, 235, 45, 143,
93, 164, 57, 187, 82, 243, 125, 133, 225, 163,
8, 121, 198, 162, 210, 249, 157, 130, 233, 161,
142, 248, 100, 66, 171, 113, 191, 100, 112, 43,
100, 31, 107, 72, 47, 118, 156, 38, 233, 218,
206, 219, 20, 91, 79, 123, 116, 35, 103, 89,
234, 186, 207, 51, 20, 21, 207, 79, 20, 52,
15, 87, 68, 62, 179, 80, 117, 252, 39, 1,
218, 128, 91, 32, 59, 88, 19, 122, 141, 227,
37, 137, 219, 38, 219, 90, 219, 123, 27, 99,
75, 105, 247, 110, 198, 172, 82, 253, 253, 129,
129, 160, 96, 120, 40, 34, 158, 153, 168, 106,
254, 175, 0, 124, 0, 33, 192, 24, 80, 10,
188, 7, 49, 194, 148, 81, 175, 124, 124, 33,
225, 216, 72, 90, 182, 187, 54, 243, 86, 197,
254, 211, 0, 93, 192, 57, 144, 18, 236, 13,
141, 197, 165, 147, 59, 45, 211, 93, 157, 249,
169, 130, 254, 225, 128, 72, 96, 54, 168, 22,
254, 142, 192, 100, 80, 43, 124, 31, 97, 200,
40, 86, 158, 190, 232, 112, 78, 164, 52, 123,
87, 99, 126, 169, 224, 126, 200, 32, 86, 152,
62, 234, 144, 79, 44, 52, 29, 215, 73, 158,
182, 232, 118, 206, 166, 212, 122, 223, 99, 24,
41, 202, 158, 215, 40, 94, 158, 184, 104, 114,
174, 165, 188, 123, 49, 227, 84, 73, 255, 118,
192, 38, 208, 26, 220, 11, 25, 199, 74, 210,
183, 29, 182, 137, 182, 230, 246, 202, 198, 215,
18, 222, 141, 152, 101, 170, 171, 63, 63, 80,
16, 60, 12, 17, 197, 204, 83, 21, 253, 207,
1, 148, 0, 111, 64, 44, 48, 29, 212, 9,
159, 70, 232, 50, 206, 149, 148, 111, 47, 108,
28, 45, 201, 221, 150, 217, 174, 218, 252, 91,
1, 251, 64, 67, 112, 49, 228, 20, 75, 79,
119, 116, 38, 167, 90, 250, 187, 3, 51, 65,
213, 240, 95, 4, 56, 3, 82, 129, 253, 160,
65, 184, 48, 114, 148, 37, 175, 91, 60, 59,
81, 211, 124, 93, 225, 249, 136, 66, 230, 177,
138, 244, 103, 7, 106, 130, 175, 33, 188, 24,
113, 202, 164, 87, 59, 126, 147, 96, 109, 232,
45, 142, 157, 164, 105, 187, 110, 243, 108, 69,
237, 243, 13, 133, 197, 163, 19, 57, 205, 210,
213, 157, 159, 41, 168, 30, 254, 136, 64, 102,
176, 42, 244, 31, 7, 72, 2, 182, 129, 182,
224, 118, 200, 38, 214, 154, 222, 235, 24, 79,
74, 180, 55, 55, 86, 150, 190, 238, 240, 76,
68, 53, 243, 87, 5, 254, 131, 0, 97, 192,
40, 80, 30, 188, 8, 113, 198, 164, 82, 251,
125, 131, 97, 161, 232, 120, 78, 162, 180, 121,
183, 98, 246, 169, 134, 254, 226, 192, 73, 144,
54, 236, 22, 205, 206, 213, 148, 95, 47, 120,
28, 34, 137, 217, 166, 218, 250, 219, 3, 27,
65, 203, 112, 87, 100, 62, 171, 80, 127, 124,
32, 33, 216, 24, 90, 138, 187, 39, 51, 90,
149, 251, 47, 3, 92, 1, 249, 192, 66, 208,
49, 156, 20, 105, 207, 110, 212, 44, 95, 93,
248, 57, 130, 146, 225, 173, 136, 125, 166, 161,
186, 248, 115, 2, 165, 193, 187, 16, 115, 76,
37, 245, 219, 7, 27, 66, 139, 113, 167, 100,
122, 171, 99, 63, 105, 208, 46, 220, 28, 89,
201, 250, 214, 195, 30, 209, 200, 92, 86, 185,
254, 242, 192, 69, 144, 51, 44, 21, 221, 207,
25, 148, 10, 239, 71, 12, 50, 133, 213, 163,
31, 57, 200, 18, 214, 141, 158, 229, 168, 75,
62, 183, 80, 118, 188, 38, 241, 218, 196, 91,
19, 123, 77, 227, 117, 137, 231, 38, 202, 154,
215, 43, 30, 159, 72, 104, 54, 174, 150, 252,
110, 193, 236, 80, 77, 252, 53, 129, 215, 32,
94, 152, 56, 106, 146, 175, 45, 188, 29, 177,
201, 180, 86, 247, 126, 198, 160, 82, 248, 61,
130, 145, 161, 172, 120, 125, 226, 161, 137, 184,
102, 242, 170, 197, 191, 19, 48, 13, 212, 5,
159, 67, 40, 49, 222, 148, 88, 111, 122, 172,
35, 61, 217, 209, 154, 220, 107, 25, 239, 74,
204, 55, 21, 214, 143, 30, 228, 8, 75, 70,
183, 114, 246, 165, 134, 251, 34, 195, 89, 145,
250, 236, 67, 13, 241, 197, 132, 83, 35, 125,
217, 225, 154, 200, 107, 22, 175, 78, 252, 52,
65, 215, 112, 94, 164, 56, 123, 82, 163, 125,
185, 225, 178, 200, 117, 150, 167, 46, 250, 156,
67, 41, 241, 222, 196, 88, 83, 122, 189, 227,
49, 137, 212, 102, 223, 106, 216, 47, 26, 156,
11, 41, 199, 94, 210, 184, 93, 178, 185, 181,
178, 247, 53, 134, 151, 34, 238, 153, 140, 106,
229, 239, 11, 12, 7, 69, 194, 179, 17, 181,
204, 119, 21, 230, 143, 10, 228, 7, 11, 66,
135, 113, 162, 164, 121, 187, 98, 243, 105, 133,
238, 227, 12, 73, 197, 246, 211, 6, 221, 194,
217, 145, 154, 236, 107, 13, 239, 69, 140, 51,
37, 213, 219, 31, 27, 72, 11, 118, 135, 102,
226, 170, 201, 191, 22, 240, 14, 196, 4, 83,
67, 125, 241, 225, 132, 72, 99, 118, 169, 230,
254, 202, 192, 87, 16, 62, 140, 16, 101, 204,
43, 21, 223, 79, 24, 52, 10, 151, 71, 46,
178, 156, 117, 169, 231, 62, 202, 144, 87, 44,
62, 157, 208, 105, 156, 46, 233, 220, 78, 217,
244, 90, 199, 123, 18, 163, 77, 185, 245, 178,
199, 53, 146, 151, 45, 174, 157, 188, 105, 177,
238, 244, 76, 71, 117, 242, 167, 5, 186, 131,
51, 33, 213, 216, 95, 26, 184, 11, 50, 135,
85, 162, 191, 57, 176, 18, 244, 13, 135, 69,
162, 179, 57, 181, 210, 247, 29, 134, 137, 162,
230, 249, 138, 194, 231, 17, 138, 140, 103, 37,
234, 155, 15, 43, 68, 31, 115, 72, 37, 246,
155, 6, 235, 66, 207, 113, 148, 36, 111, 91,
108, 59, 109, 211, 109, 157, 237, 169, 141, 190,
229, 176, 75, 52, 55, 87, 86, 190, 190, 240,
112, 68, 36, 51, 91, 85, 251, 127, 3, 96,
1, 232, 0, 78, 128, 52, 96, 23, 104, 14,
174, 132, 124, 99, 97, 233, 232, 78, 206, 180,
84, 119, 127, 102, 160, 42, 248, 31, 2, 136,
1, 166, 128, 122, 224, 35, 8, 25, 198, 138,
210, 231, 29, 138, 137, 167, 38, 250, 154, 195,
43, 17, 223, 76, 88, 53, 250, 151, 3, 46,
129, 220, 96, 89, 232, 58, 206, 147, 20, 109,
207, 109, 148, 45, 175, 93, 188, 57, 177, 210,
244, 93, 135, 121, 162, 162, 249, 185, 130, 242,
225, 133, 136, 99, 38, 169, 218, 254, 219, 0,
91, 64, 59, 112, 19, 100, 13, 235, 69, 143,
115, 36, 37, 219, 91, 27, 123, 75, 99, 119,
105, 230, 174, 202, 252, 87, 1, 254, 128, 64,
96, 48, 40, 20, 30, 143, 72, 100, 54, 171,
86, 255, 126, 192, 32, 80, 24, 60, 10, 145,
199, 44, 82, 157, 253, 169, 129, 190, 224, 112,
72, 36, 54, 155, 86, 235, 126, 207, 96, 84,
40, 63, 94, 144, 56, 108, 18, 173, 205, 189,
149, 177, 175, 52, 124, 23, 97, 206, 168, 84,
126, 191, 96, 112, 40, 36, 30, 155, 72, 107,
118, 175, 102, 252, 42, 193, 223, 16, 88, 12,
58, 133, 211, 35, 29, 217, 201, 154, 214, 235,
30, 207, 72, 84, 54, 191, 86, 240, 62, 196,
16, 83, 76, 61, 245, 209, 135, 28, 98, 137,
233, 166, 206, 250, 212, 67, 31, 113, 200, 36,
86, 155, 126, 235, 96, 79, 104, 52, 46, 151,
92, 110, 185, 236, 114, 205, 229, 149, 139, 47,
39, 92, 26, 185, 203, 50, 215, 85, 158, 191,
40, 112, 30, 164, 8, 123, 70, 163, 114, 249,
229, 130, 203, 33, 151, 88, 110, 186, 172, 115,
61, 229, 209, 139, 28, 103, 73, 234, 182, 207,
54, 212, 22, 223, 78, 216, 52, 90, 151, 123,
46, 163, 92, 121, 249, 226, 194, 201, 145, 150,
236, 110, 205, 236, 85, 141, 255, 37, 128, 27,
32, 11, 88, 7, 122, 130, 163, 33, 185, 216,
114, 218, 165, 155, 59, 43, 83, 95, 125, 248,
33, 130, 152, 97, 170, 168, 127, 62, 160, 16,
120, 12, 34, 133, 217, 163, 26, 249, 203, 2,
215, 65, 158, 176, 104, 116, 46, 167, 92, 122,
185, 227, 50, 201, 213, 150, 223, 46, 216, 28,
90, 137, 251, 38, 195, 90, 209, 251, 28, 67,
73, 241, 246, 196, 70, 211, 114, 221, 229, 153
};
/* ------------------------------------------------------------------------- */
/* This is the new implementation of P- and Q-parity generation.
It needs about the same computing time as the old implementation (both
with gcc -O2 on AMD 64 bit). Measurements indicate that about 280 MIPS
are needed for 48x CD speed (7.1 MB/s).
*/
static unsigned char burn_rspc_mult(unsigned char a, unsigned char b)
{
if (a == 0 || b == 0)
return 0;
/* Optimization of (a == 0 || b == 0) by D. Hugh Redelmeier
if((((int)a - 1) | ((int)b - 1)) < 0)
return 0;
*/
return gfpow[gflog[a] + gflog[b]];
/* % 255 not necessary because gfpow is unrolled up to index 510 */
}
/* Divide by polynomial 0x03. Derived from burn_rspc_div() and using the
unrolled size of the gfpow[] array.
*/
static unsigned char burn_rspc_div_3(unsigned char a)
{
if (a == 0)
return 0;
return gfpow[230 + gflog[a]];
}
static void burn_rspc_p0p1(unsigned char *sector, int col,
unsigned char *p0_lsb, unsigned char *p0_msb,
unsigned char *p1_lsb, unsigned char *p1_msb)
{
unsigned char *start, b;
unsigned int i, sum_v_lsb = 0, sum_v_msb = 0;
unsigned int hxv_lsb = 0, hxv_msb = 0;
start = sector + 12 + 2 * col;
for(i = 0; i < 24; i++) {
b = *start;
sum_v_lsb ^= b;
#ifdef Libburn_use_h_matriceS
hxv_lsb ^= burn_rspc_mult(b, h26[i]);
#else
hxv_lsb ^= burn_rspc_mult(b, gfpow[25 - i]);
#endif
b = *(start + 1);
sum_v_msb ^= b;
#ifdef Libburn_use_h_matriceS
hxv_msb ^= burn_rspc_mult(b, h26[i]);
#else
hxv_msb ^= burn_rspc_mult(b, gfpow[25 - i]);
#endif
start += 86;
}
/* 3 = gfpow[1] ^ gfpow[0] , 2 = gfpow[1] */
*p0_lsb = burn_rspc_div_3(burn_rspc_mult(2, sum_v_lsb) ^ hxv_lsb);
*p0_msb = burn_rspc_div_3(burn_rspc_mult(2, sum_v_msb) ^ hxv_msb);
*p1_lsb = sum_v_lsb ^ *p0_lsb;
*p1_msb = sum_v_msb ^ *p0_msb;
}
void burn_rspc_parity_p(unsigned char *sector)
{
int i;
unsigned char p0_lsb, p0_msb, p1_lsb, p1_msb;
/* Loop over P columns */
for(i = 0; i < 43; i++) {
burn_rspc_p0p1(sector, i, &p0_lsb, &p0_msb, &p1_lsb, &p1_msb);
sector[2162 + 2 * i] = p0_lsb;
sector[2162 + 2 * i + 1] = p0_msb;
sector[2076 + 2 * i] = p1_lsb;
sector[2076 + 2 * i + 1] = p1_msb;
#ifdef Libburn_with_lec_generatoR
if(verbous) {
printf("p %2d : %2.2X %2.2X ", i,
(unsigned int) p0_lsb, (unsigned int) p0_msb);
printf("%2.2X %2.2X ",
(unsigned int) p1_lsb, (unsigned int) p1_msb);
printf("-> %d,%d\n", 2162 + 2 * i, 2076 + 2 * i);
}
#endif /* Libburn_with_lec_generatoR */
}
}
static void burn_rspc_q0q1(unsigned char *sector, int diag,
unsigned char *q0_lsb, unsigned char *q0_msb,
unsigned char *q1_lsb, unsigned char *q1_msb)
{
unsigned char *start, b;
unsigned int i, idx, sum_v_lsb = 0, sum_v_msb = 0;
unsigned int hxv_lsb = 0, hxv_msb = 0;
start = sector + 12;
idx = 2 * 43 * diag;
for(i = 0; i < 43; i++) {
if (idx >= 2236)
idx -= 2236;
b = start[idx];
sum_v_lsb ^= b;
#ifdef Libburn_use_h_matriceS
hxv_lsb ^= burn_rspc_mult(b, h45[i]);
#else
hxv_lsb ^= burn_rspc_mult(b, gfpow[44 - i]);
#endif
b = start[idx + 1];
sum_v_msb ^= b;
#ifdef Libburn_use_h_matriceS
hxv_msb ^= burn_rspc_mult(b, h45[i]);
#else
hxv_msb ^= burn_rspc_mult(b, gfpow[44 - i]);
#endif
idx += 88;
}
/* 3 = gfpow[1] ^ gfpow[0] , 2 = gfpow[1] */
*q0_lsb = burn_rspc_div_3(burn_rspc_mult(2, sum_v_lsb) ^ hxv_lsb);
*q0_msb = burn_rspc_div_3(burn_rspc_mult(2, sum_v_msb) ^ hxv_msb);
*q1_lsb = sum_v_lsb ^ *q0_lsb;
*q1_msb = sum_v_msb ^ *q0_msb;
}
void burn_rspc_parity_q(unsigned char *sector)
{
int i;
unsigned char q0_lsb, q0_msb, q1_lsb, q1_msb;
/* Loop over Q diagonals */
for(i = 0; i < 26; i++) {
burn_rspc_q0q1(sector, i, &q0_lsb, &q0_msb, &q1_lsb, &q1_msb);
sector[2300 + 2 * i] = q0_lsb;
sector[2300 + 2 * i + 1] = q0_msb;
sector[2248 + 2 * i] = q1_lsb;
sector[2248 + 2 * i + 1] = q1_msb;
#ifdef Libburn_with_lec_generatoR
if(verbous) {
printf("q %2d : %2.2X %2.2X ", i,
(unsigned int) q0_lsb, (unsigned int) q0_msb);
printf("%2.2X %2.2X ",
(unsigned int) q1_lsb, (unsigned int) q1_msb);
printf("-> %d,%d\n", 2300 + 2 * i, 2248 + 2 * i);
}
#endif /* Libburn_with_lec_generatoR */
}
}
/* ------------------------------------------------------------------------- */
/* The new implementation of the ECMA-130 Annex B scrambler.
It is totally unoptimized. One should make use of larger word operations.
Measurements indicate that about 50 MIPS are needed for 48x CD speed.
*/
void burn_ecma130_scramble(unsigned char *sector)
{
int i;
unsigned char *s;
s = sector + 12;
for (i = 0; i < 2340; i++)
s[i] ^= ecma_130_annex_b[i];
}
/* ------------------------------------------------------------------------- */
/* The following code is not needed for libburn but rather documents the
origin of the tables above. In libburn it will not be compiled.
*/
#ifdef Libburn_with_lec_generatoR
/* This function produced the content of gflog[] and gfpow[]
*/
static int burn_rspc_setup_tables(void)
{
unsigned int b, l;
memset(gflog, 0, sizeof(gflog));
memset(gfpow, 0, sizeof(gfpow));
b = 1;
for (l = 0; l < 255; l++) {
gfpow[l] = (unsigned char) b;
gflog[b] = (unsigned char) l;
b = b << 1;
if (b & 256)
b = b ^ 0x11d;
}
return 0;
}
/* This function printed the content of gflog[] and gfpow[] as C code
and compared the content with the tables of the old implementation.
h26[] and h45[] are reverted order copies of gfpow[]
*/
static int burn_rspc_print_tables(void)
{
int i;
printf("static unsigned char gfpow[255] = {");
printf("\n\t");
for(i= 0; i < 255; i++) {
printf("%3u, ", gfpow[i]);
#ifdef Libburn_with_old_lec_comparisoN
if(gfpow[i] != gf8_ilog[i])
fprintf(stderr, "*** ILOG %d : %d != %d ***\n", i, gfpow[i], gf8_ilog[i]);
#endif
if((i % 10) == 9)
printf("\n\t");
}
printf("\n};\n\n");
printf("static unsigned char gflog[256] = {");
printf("\n\t");
for(i= 0; i < 256; i++) {
printf(" %3u,", gflog[i]);
#ifdef Libburn_with_old_lec_comparisoN
if(gflog[i] != gf8_log[i])
fprintf(stderr, "*** LOG %d : %d != %d ***\n", i, gflog[i], gf8_log[i]);
#endif
if((i % 10) == 9)
printf("\n\t");
}
printf("\n};\n\n");
printf("static unsigned char h26[26] = {");
printf("\n\t");
for(i= 0; i < 26; i++) {
printf(" %3u,", gfpow[25 - i]);
if((i % 10) == 9)
printf("\n\t");
}
printf("\n};\n\n");
printf("static unsigned char h45[45] = {");
printf("\n\t");
for(i= 0; i < 45; i++) {
printf(" %3u,",gfpow[44 - i]);
if((i % 10) == 9)
printf("\n\t");
}
printf("\n};\n\n");
return 0;
}
/* This code was used to generate the content of array ecma_130_annex_b[].
*/
static unsigned short ecma_130_fsr = 1;
static int next_bit(void)
{
int ret;
ret = ecma_130_fsr & 1;
ecma_130_fsr = (ecma_130_fsr >> 1) & 0x3fff;
if (ret ^ (ecma_130_fsr & 1))
ecma_130_fsr |= 0x4000;
return ret;
}
static int print_ecma_130_scrambler(void)
{
int i, j, b;
ecma_130_fsr = 1;
printf("static unsigned char ecma_130_annex_b[2340] = {");
printf("\n\t");
for (i = 0; i < 2340; i++) {
b = 0;
for (j = 0; j < 8; j++)
b |= next_bit() << j;
printf("%3u, ", b);
if ((i % 10) == 9)
printf("\n\t");
}
printf("\n};\n");
return 1;
}
#ifdef Libburn_with_general_rspc_diV
/* This is a general polynomial division function.
burn_rspc_div_3() has been derived from this by setting b to constant 3.
*/
static unsigned char burn_rspc_div(unsigned char a, unsigned char b)
{
int d;
if (a == 0)
return 0;
if (b == 0)
return -1;
d = gflog[a] - gflog[b];
if (d < 0)
d += 255;
return gfpow[d];
}
#endif /* Libburn_with_general_rspc_diV */
#endif /* Libburn_with_lec_generatoR */

24
libburn/ecma130ab.h Normal file
View File

@ -0,0 +1,24 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* ts A91016 : libburn/ecma130ab.h is the replacement for old libburn/lec.h
Copyright 2009, Thomas Schmitt <scdbackup@gmx.net>, libburnia-project.org
Provided under GPL version 2 or later.
This code module implements the computations prescribed in ECMA-130 Annex A
and B. For explanations of the underlying mathematics see ecma130ab.c .
*/
#ifndef Libburn_ecma130ab_includeD
#define Libburn_ecma130ab_includeD 1
void burn_rspc_parity_p(unsigned char *sector);
void burn_rspc_parity_q(unsigned char *sector);
void burn_ecma130_scramble(unsigned char *sector);
#endif /* ! Libburn_ecma130ab_includeD */

View File

@ -1,5 +1,16 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
@ -9,6 +20,8 @@
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <pthread.h>
#include "source.h"
#include "libburn.h"
#include "file.h"
@ -25,8 +38,6 @@ an unreadable disc */
/* This is a generic OS oriented function wrapper which compensates
shortcommings of read() in respect to a guaranteed amount of return data.
See man 2 read , paragraph "RETURN VALUE".
Possibly libburn/file.c is not the right storage location for this.
To make it ready for a move, this function is not declared static.
*/
static int read_full_buffer(int fd, unsigned char *buffer, int size)
{
@ -82,7 +93,9 @@ static off_t file_size(struct burn_source *source)
if (fs->fixed_size > 0)
return fs->fixed_size;
if (fstat(fs->datafd, &buf) == -1)
if (fstat(fs->datafd, &buf) != 0)
return (off_t) 0;
if ((buf.st_mode & S_IFMT) != S_IFREG)
return (off_t) 0;
return (off_t) buf.st_size;
}
@ -209,7 +222,7 @@ static int fifo_read(struct burn_source *source,
int size)
{
struct burn_source_fifo *fs = source->data;
int ret, todo, rpos, bufsize, diff;
int ret, todo, rpos, bufsize, diff, counted = 0;
if (fs->end_of_consumption) {
/* ??? msg: reading has been ended already */;
@ -254,6 +267,9 @@ static int fifo_read(struct burn_source *source,
"Forwarded input error ends output", 0, 0);
return -1;
}
if (!counted)
fs->empty_counter++;
counted = 1;
fifo_sleep(0);
}
diff = fs->buf_writepos - rpos; /* read volatile only once */
@ -283,6 +299,7 @@ static int fifo_read(struct burn_source *source,
(size - todo), fs->buf_readpos, (double) fs->out_counter);
*/
fs->get_counter++;
return (size - todo);
}
@ -307,10 +324,13 @@ static void fifo_free(struct burn_source *source)
{
struct burn_source_fifo *fs = source->data;
burn_fifo_abort(fs, 0);
if (fs->inp != NULL)
burn_source_free(fs->inp);
if (fs->buf != NULL)
free(fs->buf);
burn_os_free_buffer(fs->buf,
((size_t) fs->chunksize) * (size_t) fs->chunks, 0);
free((char *) fs);
}
@ -318,17 +338,22 @@ static void fifo_free(struct burn_source *source)
int burn_fifo_source_shoveller(struct burn_source *source, int flag)
{
struct burn_source_fifo *fs = source->data;
int ret, bufsize, diff, wpos, rpos, trans_end, free_bytes;
int ret, bufsize, diff, wpos, rpos, trans_end, free_bytes, fill;
int counted;
char *bufpt;
pthread_t thread_handle_storage;
fs->thread_handle= &thread_handle_storage;
*((pthread_t *) fs->thread_handle)= pthread_self();
fs->thread_pid = getpid();
fs->thread_pid_valid = 1;
fs->thread_is_valid = 1;
bufsize = fs->chunksize * fs->chunks;
while (!fs->end_of_consumption) {
/* wait for enough buffer space available */
wpos = fs->buf_writepos;
counted = 0;
while (1) {
rpos = fs->buf_readpos;
diff = rpos - wpos;
@ -339,18 +364,28 @@ int burn_fifo_source_shoveller(struct burn_source *source, int flag)
free_bytes = diff - 1;
else {
free_bytes = (bufsize - wpos) + rpos - 1;
if (bufsize - wpos < fs->chunksize)
if (bufsize - wpos < fs->inp_read_size)
trans_end = 1;
}
if (free_bytes >= fs->chunksize)
if (free_bytes >= fs->inp_read_size)
break;
if (!counted)
fs->full_counter++;
counted = 1;
fifo_sleep(0);
}
fill = bufsize - free_bytes - 1;
if (fill < fs->total_min_fill)
fs->total_min_fill = fill;
if (fill < fs->interval_min_fill)
fs->interval_min_fill = fill;
/* prepare the receiving memory */
bufpt = fs->buf + wpos;
if (trans_end) {
bufpt = calloc(fs->chunksize, 1);
bufpt = burn_os_alloc_buffer(
(size_t) fs->inp_read_size, 0);
if (bufpt == NULL) {
libdax_msgs_submit(libdax_messenger, -1,
0x00000003,
@ -364,15 +399,17 @@ int burn_fifo_source_shoveller(struct burn_source *source, int flag)
/* Obtain next chunk */
if (fs->inp->read != NULL)
ret = fs->inp->read(fs->inp,
(unsigned char *) bufpt, fs->chunksize);
(unsigned char *) bufpt, fs->inp_read_size);
else
ret = fs->inp->read_xt( fs->inp,
(unsigned char *) bufpt, fs->chunksize);
if (ret > 0)
fs->in_counter += ret;
else if (ret == 0)
(unsigned char *) bufpt, fs->inp_read_size);
if (ret == 0) {
/* >>> ??? ts B00326 */
/* >>> report EOF of fifo input and fs->in_counter */;
break; /* EOF */
else {
} else if (ret < 0) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020153,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Read error on fifo input", errno, 0);
@ -381,17 +418,21 @@ int burn_fifo_source_shoveller(struct burn_source *source, int flag)
fs->input_error = EIO;
break;
}
fs->in_counter += ret;
fs->put_counter++;
/* activate read chunk */
if (ret > fs->chunksize) /* beware of ill custom burn_source */
ret = fs->chunksize;
if (ret > fs->inp_read_size)
/* beware of ill custom burn_source */
ret = fs->inp_read_size;
if (trans_end) {
/* copy to end of buffer */
memcpy(fs->buf + wpos, bufpt, bufsize - wpos);
/* copy to start of buffer */
memcpy(fs->buf, bufpt + (bufsize - wpos),
fs->chunksize - (bufsize - wpos));
free(bufpt);
fs->inp_read_size - (bufsize - wpos));
burn_os_free_buffer(bufpt, (size_t) fs->inp_read_size,
0);
if (ret >= bufsize - wpos)
fs->buf_writepos = ret - (bufsize - wpos);
else
@ -427,9 +468,13 @@ int burn_fifo_source_shoveller(struct burn_source *source, int flag)
So in both cases the consumer is aware that reading is futile
or even fatal.
*/
free(fs->buf); /* Give up fifo buffer. Next fifo might start soon. */
if(fs->buf != NULL)
burn_os_free_buffer(fs->buf,
((size_t) fs->chunksize) * (size_t) fs->chunks, 0);
fs->buf = NULL;
fs->thread_handle= NULL;
fs->thread_is_valid = 0;
return (fs->input_error == 0);
}
@ -442,7 +487,9 @@ int burn_fifo_cancel(struct burn_source *source)
return(1);
}
/*
@param flag bit0= allow larger read chunks
*/
struct burn_source *burn_fifo_source_new(struct burn_source *inp,
int chunksize, int chunks, int flag)
{
@ -465,9 +512,14 @@ struct burn_source *burn_fifo_source_new(struct burn_source *inp,
if (fs == NULL)
return NULL;
fs->is_started = 0;
fs->thread_handle = NULL;
fs->thread_pid = 0;
fs->thread_pid_valid = 0;
fs->thread_is_valid = 0;
fs->inp = NULL; /* set later */
if (flag & 1)
fs->inp_read_size = 32 * 1024;
else
fs->inp_read_size = chunksize;
fs->chunksize = chunksize;
fs->chunks = chunks;
fs->buf = NULL;
@ -476,6 +528,9 @@ struct burn_source *burn_fifo_source_new(struct burn_source *inp,
fs->input_error = 0;
fs->end_of_consumption = 0;
fs->in_counter = fs->out_counter = 0;
fs->total_min_fill = fs->interval_min_fill = 0;
fs->put_counter = fs->get_counter = 0;
fs->empty_counter = fs->full_counter = 0;
src = burn_source_new();
if (src == NULL) {
@ -541,34 +596,89 @@ int burn_fifo_inquire_status(struct burn_source *source,
}
int burn_fifo_peek_data(struct burn_source *source, char *buf, int bufsize,
/* ts A91125 : API */
void burn_fifo_get_statistics(struct burn_source *source,
int *total_min_fill, int *interval_min_fill,
int *put_counter, int *get_counter,
int *empty_counter, int *full_counter)
{
struct burn_source_fifo *fs = source->data;
*total_min_fill = fs->total_min_fill;
*interval_min_fill = fs->interval_min_fill;
*put_counter = fs->put_counter;
*get_counter = fs->get_counter;
*empty_counter = fs->empty_counter;
*full_counter = fs->full_counter;
}
/* ts A91125 : API */
void burn_fifo_next_interval(struct burn_source *source,
int *interval_min_fill)
{
struct burn_source_fifo *fs = source->data;
int size, free_bytes, ret;
char *status_text;
*interval_min_fill = fs->interval_min_fill;
ret = burn_fifo_inquire_status(source,
&size, &free_bytes, &status_text);
fs->interval_min_fill = size - free_bytes - 1;
}
/* @param flag bit0= do not copy to buf but only wait until the fifo has read
bufsize or input ended.
The same happens if buf is NULL.
bit1= fill to max fifo size
*/
int burn_fifo_fill_data(struct burn_source *source, char *buf, int bufsize,
int flag)
{
int size, free_bytes, ret, wait_count= 0;
char *status_text;
struct burn_source_fifo *fs = source->data;
if (buf == NULL)
flag |= 1;
/* Eventually start fifo thread by reading 0 bytes */
ret = fifo_read(source, (unsigned char *) NULL, 0);
if (ret<0)
return 0;
{ret = 0; goto ex;}
/* wait for at least bufsize bytes being ready */
while (1) {
ret= burn_fifo_inquire_status(source,
&size, &free_bytes, &status_text);
if (size < bufsize) {
libdax_msgs_submit(libdax_messenger, -1, 0x0002015c,
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
"Fifo size is smaller than desired peek buffer", 0, 0);
return -1;
if (flag & 2) {
bufsize = size - (size % fs->inp_read_size) -
fs->inp_read_size;
if (bufsize <= 0)
{ret = 0; goto ex;}
}
if (size - fs->inp_read_size < bufsize) {
if (flag & 1) {
bufsize = size - (size % fs->inp_read_size) -
fs->inp_read_size;
if (bufsize <= 0)
{ret = 0; goto ex;}
} else {
libdax_msgs_submit(libdax_messenger, -1,
0x0002015c, LIBDAX_MSGS_SEV_FAILURE,
LIBDAX_MSGS_PRIO_HIGH,
"Fifo size too small for desired peek buffer",
0, 0);
{ret = -1; goto ex;}
}
}
if (fs->out_counter > 0 || (ret & 4) || fs->buf == NULL) {
libdax_msgs_submit(libdax_messenger, -1, 0x0002015e,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Fifo is already under consumption when peeking is desired",
0, 0);
return -1;
{ret = -1; goto ex;}
}
if(size - free_bytes >= bufsize) {
@ -577,17 +687,33 @@ int burn_fifo_peek_data(struct burn_source *source, char *buf, int bufsize,
"libburn_DEBUG: after waiting cycle %d : fifo %s , %d bytes\n",
wait_count, status_text, size - free_bytes);
*/
memcpy(buf, fs->buf, bufsize);
return 1;
if(!(flag & 1))
memcpy(buf, fs->buf, bufsize);
{ret = 1; goto ex;}
}
if (ret&2) { /* input has ended, not enough data arrived */
if (ret & 2) {
/* input has ended, not enough data arrived */
if (flag & 1)
{ret = 0; goto ex;}
libdax_msgs_submit(libdax_messenger, -1, 0x0002015d,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Fifo input ended short of desired peek buffer size",
0, 0);
return 0;
{ret = 0; goto ex;}
}
if (free_bytes < fs->inp_read_size) {
/* Usable fifo size filled, not enough data arrived */
if (flag & 1)
{ret = 0; goto ex;}
libdax_msgs_submit(libdax_messenger, -1, 0x00020174,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Fifo alignment does not allow desired read size",
0, 0);
{ret = 0; goto ex;}
}
usleep(100000);
wait_count++;
@ -599,5 +725,25 @@ int burn_fifo_peek_data(struct burn_source *source, char *buf, int bufsize,
*/
}
return(0);
ret = 0;
ex:;
fs->total_min_fill = fs->interval_min_fill = fs->buf_writepos;
return(ret);
}
/* ts A80713 : API */
int burn_fifo_peek_data(struct burn_source *source, char *buf, int bufsize,
int flag)
{
return burn_fifo_fill_data(source, buf, bufsize, 0);
}
/* ts A91125 : API */
int burn_fifo_fill(struct burn_source *source, int bufsize, int flag)
{
return burn_fifo_fill_data(source, NULL, bufsize,
1 | ((flag & 1) << 1));
}

View File

@ -1,5 +1,10 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifndef BURN__FILE_H
#define BURN__FILE_H
@ -29,11 +34,13 @@ struct burn_source_fifo {
*/
int is_started;
void *thread_handle; /* actually a pointer to a thread_t */
int thread_pid;
int thread_pid_valid;
int thread_is_valid;
/* the burn_source for which this fifo is acting as proxy */
struct burn_source *inp;
int inp_read_size;
/* <<< up to now it was only a pipe. This is on its way out. */
int outlet[2];
@ -50,6 +57,14 @@ struct burn_source_fifo {
off_t in_counter;
off_t out_counter;
int total_min_fill;
int interval_min_fill;
int put_counter;
int get_counter;
int empty_counter;
int full_counter;
};

View File

@ -1,5 +1,15 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <unistd.h>
/* ts A61007 */
@ -9,6 +19,7 @@
#include <signal.h>
#include <string.h>
#include <stdlib.h>
#include <pthread.h>
/* ts A70928 : init.h is for others, not for init .c
#include "init.h"
@ -32,14 +43,16 @@ struct libdax_msgs *libdax_messenger= NULL;
int burn_running = 0;
/* ts A60813 : Linux: wether to use O_EXCL on open() of device files */
/* ts A60813 : GNU/Linux: whether to use O_EXCL on open() of device files
ts B00212 : FreeBSD: whether to use flock(LOCK_EX) after open()
*/
int burn_sg_open_o_excl = 1;
/* ts A70403 : Linux: wether to use fcntl(,F_SETLK,)
/* ts A70403 : GNU/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 :
/* ts A70314 : GNU/Linux: what device family to use :
0= default family
1= sr
2= scd
@ -59,6 +72,12 @@ int burn_sg_open_o_nonblock = 1;
to unconditional abort of the process */
int burn_sg_open_abort_busy = 0;
/* The message returned from sg_id_string() and/or sg_initialize()
*/
static char sg_initialize_msg[1024] = {""};
/* ts A61002 */
#include "cleanup.h"
@ -66,15 +85,25 @@ int burn_sg_open_abort_busy = 0;
/* Parameters for builtin abort handler */
static char abort_message_prefix[81] = {"libburn : "};
static pid_t abort_control_pid= 0;
static pthread_t abort_control_thread;
volatile int burn_global_abort_level= 0;
int burn_global_abort_signum= 0;
void *burn_global_signal_handle = NULL;
burn_abort_handler_t burn_global_signal_handler = NULL;
int burn_builtin_signal_action = 0; /* burn_set_signal_handling() */
volatile int burn_builtin_triggered_action = 0; /* burn_is_aborting() */
/* ts A70223 : wether implemented untested profiles are supported */
int burn_support_untested_profiles = 0;
/* ts A91111 :
whether to log SCSI commands (to be implemented in sg-*.c)
bit0= log in /tmp/libburn_sg_command_log
bit1= log to stderr
bit2= flush every line
*/
int burn_sg_log_scsi = 0;
/* ts A60925 : ticket 74 */
/** Create the messenger object for libburn. */
@ -103,6 +132,14 @@ int burn_initialize(void)
ret = burn_msgs_initialize();
if (ret <= 0)
return 0;
ret = sg_initialize(sg_initialize_msg, 0);
if (ret <= 0) {
libdax_msgs_submit(libdax_messenger, -1,
0x00020175,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
sg_initialize_msg, 0, 0);
return 0;
}
burn_running = 1;
return 1;
}
@ -130,10 +167,22 @@ void burn_finish(void)
/* ts A60924 : ticket 74 */
libdax_msgs_destroy(&libdax_messenger,0);
sg_shutdown(0);
burn_running = 0;
}
/* ts A91226 */
/** API function. See libburn.h */
char *burn_scsi_transport_id(int flag)
{
if (!burn_running)
sg_id_string(sg_initialize_msg, 0);
return sg_initialize_msg;
}
/* ts A60813 */
/** API function. See libburn.h */
void burn_preset_device_open(int exclusive, int blocking, int abort_on_busy)
@ -288,6 +337,20 @@ int burn_sev_to_text(int severity_number, char **severity_name, int flag)
return ret;
}
/* ts B00224 */
char *burn_util_thread_id(pid_t pid, pthread_t tid, char text[80])
{
int i, l;
sprintf(text, "[%lu,", (unsigned long int) getpid());
l= strlen(text);
for(i= 0; i < sizeof(pthread_t) && 2 * i < 80 - l - 3; i++)
sprintf(text + l + 2 * i,
"%2.2X", ((unsigned char *) &tid)[i]);
sprintf(text + l + 2 * i, "]");
return text;
}
int burn_builtin_abort_handler(void *handle, int signum, int flag)
{
@ -296,15 +359,53 @@ int burn_builtin_abort_handler(void *handle, int signum, int flag)
/*
#define Libburn_signal_handler_verbouS 1
*/
int ret;
struct burn_drive *d;
#ifdef Libburn_signal_handler_verbouS
fprintf(stderr,
"libburn_ABORT: pid = %d , abort_control_pid = %d , sig= %d\n",
getpid(), abort_control_pid, signum);
char text[80];
fprintf(stderr, "libburn_ABORT: in = %s\n",
burn_util_thread_id(getpid(), pthread_self(), text));
fprintf(stderr, "libburn_ABORT: ctrl = %s\n",
burn_util_thread_id(abort_control_pid, abort_control_thread,
text));
if (burn_global_signal_handler == burn_builtin_abort_handler)
fprintf(stderr, "libburn_ABORT: signal action = %d\n",
burn_builtin_signal_action);
/* >>> find writing drives and report their tid
fprintf(stderr, "libburn_ABORT: wrt = %s\n",
burn_util_thread_id(0, burn_write_thread_id, text));
fprintf(stderr, "libburn_ABORT: sig= %d\n", signum);
*/
#endif
burn_builtin_triggered_action = burn_builtin_signal_action;
burn_global_abort_level = -1;
if (burn_builtin_signal_action > 1) {
Cleanup_set_handlers(NULL, NULL, 2);
if (burn_builtin_signal_action == 4)
return -2;
fprintf(stderr,"%sABORT : Trying to shut down busy drives\n",
abort_message_prefix);
fprintf(stderr,
"%sABORT : Wait the normal burning time before any kill -9\n",
abort_message_prefix);
burn_abort_5(0, burn_abort_pacifier, abort_message_prefix,
0, 1);
libdax_msgs_submit(libdax_messenger, -1, 0x00020177,
LIBDAX_MSGS_SEV_ABORT, LIBDAX_MSGS_PRIO_HIGH,
"Urged drive worker threads to do emergency halt",
0, 0);
return -2;
}
/* ---- old deprecated stuck-in-abort-handler loop ---- */
/* ts A70928:
Must be quick. Allowed to coincide with other thread and to share
the increment with that one. It must not decrease, though, and
@ -317,7 +418,8 @@ int burn_builtin_abort_handler(void *handle, int signum, int flag)
#ifdef Libburn_new_thread_signal_handleR
ret = burn_drive_find_by_thread_pid(&d, getpid());
ret = burn_drive_find_by_thread_pid(&d, getpid(),
pthread_self());
if (ret > 0 && d->busy == BURN_DRIVE_WRITING) {
/* This is an active writer thread */
@ -357,13 +459,13 @@ int burn_builtin_abort_handler(void *handle, int signum, int flag)
}
burn_global_abort_level = -1;
Cleanup_set_handlers(NULL, NULL, 2);
fprintf(stderr,"%sABORT : Trying to shut down drive and library\n",
abort_message_prefix);
fprintf(stderr,
"%sABORT : Wait the normal burning time before any kill -9\n",
abort_message_prefix);
close(0); /* somehow stdin as input blocks abort until EOF */
burn_abort(4440, burn_abort_pacifier, abort_message_prefix);
fprintf(stderr,
@ -373,28 +475,71 @@ int burn_builtin_abort_handler(void *handle, int signum, int flag)
return(1);
}
/* ts A61002 : API */
void burn_set_signal_handling(void *handle, burn_abort_handler_t handler,
int mode)
int mode)
{
if(handler == NULL && mode == 0) {
/*
fprintf(stderr, "libburn_experimental: burn_set_signal_handling, handler==%lx mode=%d\n", (unsigned long) handler, mode);
*/
if(handler == NULL) {
handler = burn_builtin_abort_handler;
/*
fprintf(stderr, "libburn_experimental: activated burn_builtin_abort_handler() with handle '%s'\n",(handle==NULL ? "libburn : " : (char *) handle));
if ((mode & ~4) == 0)
fprintf(stderr, "libburn_experimental: activated burn_builtin_abort_handler() with handle '%s'\n",(handle==NULL ? "libburn : " : (char *) handle));
*/
}
strcpy(abort_message_prefix, "libburn : ");
if(handle != NULL)
abort_message_prefix[0] = 0;
if(handle != NULL && handler == burn_builtin_abort_handler)
strncpy(abort_message_prefix, (char *) handle,
sizeof(abort_message_prefix)-1);
abort_message_prefix[sizeof(abort_message_prefix)-1] = 0;
abort_control_pid = getpid();
Cleanup_set_handlers(handle, (Cleanup_app_handler_T) handler, mode|4);
abort_control_thread = pthread_self();
burn_builtin_signal_action = (mode >> 4) & 15;
if((mode & 11) != 0)
burn_builtin_signal_action = 0;
if(burn_builtin_signal_action > 1)
burn_builtin_triggered_action = 0;
if(burn_builtin_signal_action == 0)
burn_builtin_signal_action = 1;
Cleanup_set_handlers(handle, (Cleanup_app_handler_T) handler,
(mode & 15) | 4);
burn_global_signal_handle = handle;
burn_global_signal_handler = handler;
}
/* ts B00304 : API */
int burn_is_aborting(int flag)
{
return burn_builtin_triggered_action;
}
/* ts B00225 */
/* @return 0= no abort action 2 pending , 1= not control thread
*/
int burn_init_catch_on_abort(int flag)
{
if (burn_builtin_triggered_action != 2)
return 0;
if (abort_control_pid != getpid() ||
abort_control_thread != pthread_self())
return 1;
burn_abort(4440, burn_abort_pacifier, abort_message_prefix);
fprintf(stderr,
"\n%sABORT : Program done. Even if you do not see a shell prompt.\n\n",
abort_message_prefix);
exit(1);
}
/* ts A70223 : API */
void burn_allow_untested_profiles(int yes)
{
@ -414,3 +559,9 @@ int burn_set_messenger(void *messenger)
return 1;
}
/* ts A91111 API */
void burn_set_scsi_logging(int flag)
{
burn_sg_log_scsi = flag & 7;
}

View File

@ -17,5 +17,15 @@ extern int burn_global_abort_signum;
extern void *burn_global_signal_handle;
extern burn_abort_handler_t burn_global_signal_handler;
extern int burn_builtin_signal_action; /* burn_set_signal_handling() */
extern volatile int burn_builtin_triggered_action; /* burn_is_aborting() */
/* ts B00225 */
/* @return 0= no abort pending , 1= not control thread ,
-1= surprisingly burn_abort returned
*/
int burn_init_catch_on_abort(int flag);
#endif /* BURN__INIT_H */

View File

@ -1,451 +0,0 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* borrowed HEAVILY from cdrdao */
#include <string.h>
#include "lec.h"
#define LEC_HEADER_OFFSET 12
#define LEC_MODE1_P_PARITY_OFFSET 2076
#define LEC_MODE1_Q_PARITY_OFFSET 2248
static unsigned char gf8_ilog[255] = {
1, 2, 4, 8, 16, 32, 64, 128, 29, 58, 116, 232, 205, 135, 19, 38, 76,
152, 45, 90, 180, 117, 234, 201, 143, 3, 6, 12, 24, 48, 96,
192, 157, 39, 78, 156, 37, 74, 148, 53, 106, 212, 181, 119,
238, 193, 159, 35, 70, 140, 5, 10, 20, 40, 80, 160, 93, 186,
105, 210, 185, 111, 222, 161, 95, 190, 97, 194, 153, 47, 94,
188, 101, 202, 137, 15, 30, 60, 120, 240, 253, 231, 211, 187,
107, 214, 177, 127, 254, 225, 223, 163, 91, 182, 113, 226, 217,
175, 67, 134, 17, 34, 68, 136, 13, 26, 52, 104, 208, 189, 103,
206, 129, 31, 62, 124, 248, 237, 199, 147, 59, 118, 236, 197,
151, 51, 102, 204, 133, 23, 46, 92, 184, 109, 218, 169, 79,
158, 33, 66, 132, 21, 42, 84, 168, 77, 154, 41, 82, 164, 85,
170, 73, 146, 57, 114, 228, 213, 183, 115, 230, 209, 191, 99,
198, 145, 63, 126, 252, 229, 215, 179, 123, 246, 241, 255, 227,
219, 171, 75, 150, 49, 98, 196, 149, 55, 110, 220, 165, 87,
174, 65, 130, 25, 50, 100, 200, 141, 7, 14, 28, 56, 112, 224,
221, 167, 83, 166, 81, 162, 89, 178, 121, 242, 249, 239, 195,
155, 43, 86, 172, 69, 138, 9, 18, 36, 72, 144, 61, 122, 244,
245, 247, 243, 251, 235, 203, 139, 11, 22, 44, 88, 176, 125,
250, 233, 207, 131, 27, 54, 108, 216, 173, 71, 142,
};
static unsigned char gf8_log[256] = {
0, 0, 1, 25, 2, 50, 26, 198, 3, 223, 51, 238, 27, 104, 199, 75, 4, 100,
224, 14, 52, 141, 239, 129, 28, 193, 105, 248, 200, 8, 76, 113,
5, 138, 101, 47, 225, 36, 15, 33, 53, 147, 142, 218, 240, 18,
130, 69, 29, 181, 194, 125, 106, 39, 249, 185, 201, 154, 9,
120, 77, 228, 114, 166, 6, 191, 139, 98, 102, 221, 48, 253,
226, 152, 37, 179, 16, 145, 34, 136, 54, 208, 148, 206, 143,
150, 219, 189, 241, 210, 19, 92, 131, 56, 70, 64, 30, 66, 182,
163, 195, 72, 126, 110, 107, 58, 40, 84, 250, 133, 186, 61,
202, 94, 155, 159, 10, 21, 121, 43, 78, 212, 229, 172, 115,
243, 167, 87, 7, 112, 192, 247, 140, 128, 99, 13, 103, 74, 222,
237, 49, 197, 254, 24, 227, 165, 153, 119, 38, 184, 180, 124,
17, 68, 146, 217, 35, 32, 137, 46, 55, 63, 209, 91, 149, 188,
207, 205, 144, 135, 151, 178, 220, 252, 190, 97, 242, 86, 211,
171, 20, 42, 93, 158, 132, 60, 57, 83, 71, 109, 65, 162, 31,
45, 67, 216, 183, 123, 164, 118, 196, 23, 73, 236, 127, 12,
111, 246, 108, 161, 59, 82, 41, 157, 85, 170, 251, 96, 134,
177, 187, 204, 62, 90, 203, 89, 95, 176, 156, 169, 160, 81, 11,
245, 22, 235, 122, 117, 44, 215, 79, 174, 213, 233, 230, 231,
173, 232, 116, 214, 244, 234, 168, 80, 88, 175,
};
static unsigned char gf8_q_coeffs[2][45] = {
{97, 251, 133, 60, 82, 160, 155, 201, 8, 112, 246, 11, 21, 42, 157,
169, 80, 174, 232, 230, 172, 211, 241, 18, 68, 216, 44, 121, 9, 200,
75, 103, 221, 252, 96, 176, 88, 167, 114, 76, 199, 26, 1, 0, 0},
{190, 96, 250, 132, 59, 81, 159, 154, 200, 7, 111, 245, 10, 20, 41,
156, 168, 79, 173, 231, 229, 171, 210, 240, 17, 67, 215, 43, 120, 8,
199, 74, 102, 220, 251, 95, 175, 87, 166, 113, 75, 198, 25, 0, 0}
};
static unsigned char gf8_p_coeffs[2][26] = {
{230, 172, 211, 241, 18, 68, 216, 44, 121, 9, 200, 75, 103, 221, 252,
96, 176, 88, 167, 114, 76, 199, 26, 1, 0, 0},
{231, 229, 171, 210, 240, 17, 67, 215, 43, 120, 8, 199, 74, 102, 220,
251, 95, 175, 87, 166, 113, 75, 198, 25, 0, 0}
};
static unsigned char yellowbook_scrambler[2340] = {
1, 128, 0, 96, 0, 40, 0, 30, 128, 8, 96, 6, 168, 2, 254, 129, 128, 96,
96, 40, 40, 30, 158,
136, 104, 102, 174, 170, 252, 127, 1, 224, 0, 72, 0, 54, 128, 22, 224,
14, 200, 4, 86, 131, 126, 225,
224, 72, 72, 54, 182, 150, 246, 238, 198, 204, 82, 213, 253, 159, 1,
168, 0, 126, 128, 32, 96, 24, 40,
10, 158, 135, 40, 98, 158, 169, 168, 126, 254, 160, 64, 120, 48, 34,
148, 25, 175, 74, 252, 55, 1, 214,
128, 94, 224, 56, 72, 18, 182, 141, 182, 229, 182, 203, 54, 215, 86,
222, 190, 216, 112, 90, 164, 59, 59,
83, 83, 125, 253, 225, 129, 136, 96, 102, 168, 42, 254, 159, 0, 104, 0,
46, 128, 28, 96, 9, 232, 6,
206, 130, 212, 97, 159, 104, 104, 46, 174, 156, 124, 105, 225, 238,
200, 76, 86, 181, 254, 247, 0, 70, 128,
50, 224, 21, 136, 15, 38, 132, 26, 227, 75, 9, 247, 70, 198, 178, 210,
245, 157, 135, 41, 162, 158, 249,
168, 66, 254, 177, 128, 116, 96, 39, 104, 26, 174, 139, 60, 103, 81,
234, 188, 79, 49, 244, 20, 71, 79,
114, 180, 37, 183, 91, 54, 187, 86, 243, 126, 197, 224, 83, 8, 61, 198,
145, 146, 236, 109, 141, 237, 165,
141, 187, 37, 179, 91, 53, 251, 87, 3, 126, 129, 224, 96, 72, 40, 54,
158, 150, 232, 110, 206, 172, 84,
125, 255, 97, 128, 40, 96, 30, 168, 8, 126, 134, 160, 98, 248, 41, 130,
158, 225, 168, 72, 126, 182, 160,
118, 248, 38, 194, 154, 209, 171, 28, 127, 73, 224, 54, 200, 22, 214,
142, 222, 228, 88, 75, 122, 183, 99,
54, 169, 214, 254, 222, 192, 88, 80, 58, 188, 19, 49, 205, 212, 85,
159, 127, 40, 32, 30, 152, 8, 106,
134, 175, 34, 252, 25, 129, 202, 224, 87, 8, 62, 134, 144, 98, 236, 41,
141, 222, 229, 152, 75, 42, 183,
95, 54, 184, 22, 242, 142, 197, 164, 83, 59, 125, 211, 97, 157, 232,
105, 142, 174, 228, 124, 75, 97, 247,
104, 70, 174, 178, 252, 117, 129, 231, 32, 74, 152, 55, 42, 150, 159,
46, 232, 28, 78, 137, 244, 102, 199,
106, 210, 175, 29, 188, 9, 177, 198, 244, 82, 199, 125, 146, 161, 173,
184, 125, 178, 161, 181, 184, 119, 50,
166, 149, 186, 239, 51, 12, 21, 197, 207, 19, 20, 13, 207, 69, 148, 51,
47, 85, 220, 63, 25, 208, 10,
220, 7, 25, 194, 138, 209, 167, 28, 122, 137, 227, 38, 201, 218, 214,
219, 30, 219, 72, 91, 118, 187, 102,
243, 106, 197, 239, 19, 12, 13, 197, 197, 147, 19, 45, 205, 221, 149,
153, 175, 42, 252, 31, 1, 200, 0,
86, 128, 62, 224, 16, 72, 12, 54, 133, 214, 227, 30, 201, 200, 86, 214,
190, 222, 240, 88, 68, 58, 179,
83, 53, 253, 215, 1, 158, 128, 104, 96, 46, 168, 28, 126, 137, 224,
102, 200, 42, 214, 159, 30, 232, 8,
78, 134, 180, 98, 247, 105, 134, 174, 226, 252, 73, 129, 246, 224, 70,
200, 50, 214, 149, 158, 239, 40, 76,
30, 181, 200, 119, 22, 166, 142, 250, 228, 67, 11, 113, 199, 100, 82,
171, 125, 191, 97, 176, 40, 116, 30,
167, 72, 122, 182, 163, 54, 249, 214, 194, 222, 209, 152, 92, 106, 185,
239, 50, 204, 21, 149, 207, 47, 20,
28, 15, 73, 196, 54, 211, 86, 221, 254, 217, 128, 90, 224, 59, 8, 19,
70, 141, 242, 229, 133, 139, 35,
39, 89, 218, 186, 219, 51, 27, 85, 203, 127, 23, 96, 14, 168, 4, 126,
131, 96, 97, 232, 40, 78, 158,
180, 104, 119, 110, 166, 172, 122, 253, 227, 1, 137, 192, 102, 208, 42,
220, 31, 25, 200, 10, 214, 135, 30,
226, 136, 73, 166, 182, 250, 246, 195, 6, 209, 194, 220, 81, 153, 252,
106, 193, 239, 16, 76, 12, 53, 197,
215, 19, 30, 141, 200, 101, 150, 171, 46, 255, 92, 64, 57, 240, 18,
196, 13, 147, 69, 173, 243, 61, 133,
209, 163, 28, 121, 201, 226, 214, 201, 158, 214, 232, 94, 206, 184, 84,
114, 191, 101, 176, 43, 52, 31, 87,
72, 62, 182, 144, 118, 236, 38, 205, 218, 213, 155, 31, 43, 72, 31,
118, 136, 38, 230, 154, 202, 235, 23,
15, 78, 132, 52, 99, 87, 105, 254, 174, 192, 124, 80, 33, 252, 24, 65,
202, 176, 87, 52, 62, 151, 80,
110, 188, 44, 113, 221, 228, 89, 139, 122, 231, 99, 10, 169, 199, 62,
210, 144, 93, 172, 57, 189, 210, 241,
157, 132, 105, 163, 110, 249, 236, 66, 205, 241, 149, 132, 111, 35,
108, 25, 237, 202, 205, 151, 21, 174, 143,
60, 100, 17, 235, 76, 79, 117, 244, 39, 7, 90, 130, 187, 33, 179, 88,
117, 250, 167, 3, 58, 129, 211,
32, 93, 216, 57, 154, 146, 235, 45, 143, 93, 164, 57, 187, 82, 243,
125, 133, 225, 163, 8, 121, 198, 162,
210, 249, 157, 130, 233, 161, 142, 248, 100, 66, 171, 113, 191, 100,
112, 43, 100, 31, 107, 72, 47, 118, 156,
38, 233, 218, 206, 219, 20, 91, 79, 123, 116, 35, 103, 89, 234, 186,
207, 51, 20, 21, 207, 79, 20, 52,
15, 87, 68, 62, 179, 80, 117, 252, 39, 1, 218, 128, 91, 32, 59, 88, 19,
122, 141, 227, 37, 137, 219,
38, 219, 90, 219, 123, 27, 99, 75, 105, 247, 110, 198, 172, 82, 253,
253, 129, 129, 160, 96, 120, 40, 34,
158, 153, 168, 106, 254, 175, 0, 124, 0, 33, 192, 24, 80, 10, 188, 7,
49, 194, 148, 81, 175, 124, 124,
33, 225, 216, 72, 90, 182, 187, 54, 243, 86, 197, 254, 211, 0, 93, 192,
57, 144, 18, 236, 13, 141, 197,
165, 147, 59, 45, 211, 93, 157, 249, 169, 130, 254, 225, 128, 72, 96,
54, 168, 22, 254, 142, 192, 100, 80,
43, 124, 31, 97, 200, 40, 86, 158, 190, 232, 112, 78, 164, 52, 123, 87,
99, 126, 169, 224, 126, 200, 32,
86, 152, 62, 234, 144, 79, 44, 52, 29, 215, 73, 158, 182, 232, 118,
206, 166, 212, 122, 223, 99, 24, 41,
202, 158, 215, 40, 94, 158, 184, 104, 114, 174, 165, 188, 123, 49, 227,
84, 73, 255, 118, 192, 38, 208, 26,
220, 11, 25, 199, 74, 210, 183, 29, 182, 137, 182, 230, 246, 202, 198,
215, 18, 222, 141, 152, 101, 170, 171,
63, 63, 80, 16, 60, 12, 17, 197, 204, 83, 21, 253, 207, 1, 148, 0, 111,
64, 44, 48, 29, 212, 9,
159, 70, 232, 50, 206, 149, 148, 111, 47, 108, 28, 45, 201, 221, 150,
217, 174, 218, 252, 91, 1, 251, 64,
67, 112, 49, 228, 20, 75, 79, 119, 116, 38, 167, 90, 250, 187, 3, 51,
65, 213, 240, 95, 4, 56, 3,
82, 129, 253, 160, 65, 184, 48, 114, 148, 37, 175, 91, 60, 59, 81, 211,
124, 93, 225, 249, 136, 66, 230,
177, 138, 244, 103, 7, 106, 130, 175, 33, 188, 24, 113, 202, 164, 87,
59, 126, 147, 96, 109, 232, 45, 142,
157, 164, 105, 187, 110, 243, 108, 69, 237, 243, 13, 133, 197, 163, 19,
57, 205, 210, 213, 157, 159, 41, 168,
30, 254, 136, 64, 102, 176, 42, 244, 31, 7, 72, 2, 182, 129, 182, 224,
118, 200, 38, 214, 154, 222, 235,
24, 79, 74, 180, 55, 55, 86, 150, 190, 238, 240, 76, 68, 53, 243, 87,
5, 254, 131, 0, 97, 192, 40,
80, 30, 188, 8, 113, 198, 164, 82, 251, 125, 131, 97, 161, 232, 120,
78, 162, 180, 121, 183, 98, 246, 169,
134, 254, 226, 192, 73, 144, 54, 236, 22, 205, 206, 213, 148, 95, 47,
120, 28, 34, 137, 217, 166, 218, 250,
219, 3, 27, 65, 203, 112, 87, 100, 62, 171, 80, 127, 124, 32, 33, 216,
24, 90, 138, 187, 39, 51, 90,
149, 251, 47, 3, 92, 1, 249, 192, 66, 208, 49, 156, 20, 105, 207, 110,
212, 44, 95, 93, 248, 57, 130,
146, 225, 173, 136, 125, 166, 161, 186, 248, 115, 2, 165, 193, 187, 16,
115, 76, 37, 245, 219, 7, 27, 66,
139, 113, 167, 100, 122, 171, 99, 63, 105, 208, 46, 220, 28, 89, 201,
250, 214, 195, 30, 209, 200, 92, 86,
185, 254, 242, 192, 69, 144, 51, 44, 21, 221, 207, 25, 148, 10, 239,
71, 12, 50, 133, 213, 163, 31, 57,
200, 18, 214, 141, 158, 229, 168, 75, 62, 183, 80, 118, 188, 38, 241,
218, 196, 91, 19, 123, 77, 227, 117,
137, 231, 38, 202, 154, 215, 43, 30, 159, 72, 104, 54, 174, 150, 252,
110, 193, 236, 80, 77, 252, 53, 129,
215, 32, 94, 152, 56, 106, 146, 175, 45, 188, 29, 177, 201, 180, 86,
247, 126, 198, 160, 82, 248, 61, 130,
145, 161, 172, 120, 125, 226, 161, 137, 184, 102, 242, 170, 197, 191,
19, 48, 13, 212, 5, 159, 67, 40, 49,
222, 148, 88, 111, 122, 172, 35, 61, 217, 209, 154, 220, 107, 25, 239,
74, 204, 55, 21, 214, 143, 30, 228,
8, 75, 70, 183, 114, 246, 165, 134, 251, 34, 195, 89, 145, 250, 236,
67, 13, 241, 197, 132, 83, 35, 125,
217, 225, 154, 200, 107, 22, 175, 78, 252, 52, 65, 215, 112, 94, 164,
56, 123, 82, 163, 125, 185, 225, 178,
200, 117, 150, 167, 46, 250, 156, 67, 41, 241, 222, 196, 88, 83, 122,
189, 227, 49, 137, 212, 102, 223, 106,
216, 47, 26, 156, 11, 41, 199, 94, 210, 184, 93, 178, 185, 181, 178,
247, 53, 134, 151, 34, 238, 153, 140,
106, 229, 239, 11, 12, 7, 69, 194, 179, 17, 181, 204, 119, 21, 230,
143, 10, 228, 7, 11, 66, 135, 113,
162, 164, 121, 187, 98, 243, 105, 133, 238, 227, 12, 73, 197, 246, 211,
6, 221, 194, 217, 145, 154, 236, 107,
13, 239, 69, 140, 51, 37, 213, 219, 31, 27, 72, 11, 118, 135, 102, 226,
170, 201, 191, 22, 240, 14, 196,
4, 83, 67, 125, 241, 225, 132, 72, 99, 118, 169, 230, 254, 202, 192,
87, 16, 62, 140, 16, 101, 204, 43,
21, 223, 79, 24, 52, 10, 151, 71, 46, 178, 156, 117, 169, 231, 62, 202,
144, 87, 44, 62, 157, 208, 105,
156, 46, 233, 220, 78, 217, 244, 90, 199, 123, 18, 163, 77, 185, 245,
178, 199, 53, 146, 151, 45, 174, 157,
188, 105, 177, 238, 244, 76, 71, 117, 242, 167, 5, 186, 131, 51, 33,
213, 216, 95, 26, 184, 11, 50, 135,
85, 162, 191, 57, 176, 18, 244, 13, 135, 69, 162, 179, 57, 181, 210,
247, 29, 134, 137, 162, 230, 249, 138,
194, 231, 17, 138, 140, 103, 37, 234, 155, 15, 43, 68, 31, 115, 72, 37,
246, 155, 6, 235, 66, 207, 113,
148, 36, 111, 91, 108, 59, 109, 211, 109, 157, 237, 169, 141, 190, 229,
176, 75, 52, 55, 87, 86, 190, 190,
240, 112, 68, 36, 51, 91, 85, 251, 127, 3, 96, 1, 232, 0, 78, 128, 52,
96, 23, 104, 14, 174, 132,
124, 99, 97, 233, 232, 78, 206, 180, 84, 119, 127, 102, 160, 42, 248,
31, 2, 136, 1, 166, 128, 122, 224,
35, 8, 25, 198, 138, 210, 231, 29, 138, 137, 167, 38, 250, 154, 195,
43, 17, 223, 76, 88, 53, 250, 151,
3, 46, 129, 220, 96, 89, 232, 58, 206, 147, 20, 109, 207, 109, 148, 45,
175, 93, 188, 57, 177, 210, 244,
93, 135, 121, 162, 162, 249, 185, 130, 242, 225, 133, 136, 99, 38, 169,
218, 254, 219, 0, 91, 64, 59, 112,
19, 100, 13, 235, 69, 143, 115, 36, 37, 219, 91, 27, 123, 75, 99, 119,
105, 230, 174, 202, 252, 87, 1,
254, 128, 64, 96, 48, 40, 20, 30, 143, 72, 100, 54, 171, 86, 255, 126,
192, 32, 80, 24, 60, 10, 145,
199, 44, 82, 157, 253, 169, 129, 190, 224, 112, 72, 36, 54, 155, 86,
235, 126, 207, 96, 84, 40, 63, 94,
144, 56, 108, 18, 173, 205, 189, 149, 177, 175, 52, 124, 23, 97, 206,
168, 84, 126, 191, 96, 112, 40, 36,
30, 155, 72, 107, 118, 175, 102, 252, 42, 193, 223, 16, 88, 12, 58,
133, 211, 35, 29, 217, 201, 154, 214,
235, 30, 207, 72, 84, 54, 191, 86, 240, 62, 196, 16, 83, 76, 61, 245,
209, 135, 28, 98, 137, 233, 166,
206, 250, 212, 67, 31, 113, 200, 36, 86, 155, 126, 235, 96, 79, 104,
52, 46, 151, 92, 110, 185, 236, 114,
205, 229, 149, 139, 47, 39, 92, 26, 185, 203, 50, 215, 85, 158, 191,
40, 112, 30, 164, 8, 123, 70, 163,
114, 249, 229, 130, 203, 33, 151, 88, 110, 186, 172, 115, 61, 229, 209,
139, 28, 103, 73, 234, 182, 207, 54,
212, 22, 223, 78, 216, 52, 90, 151, 123, 46, 163, 92, 121, 249, 226,
194, 201, 145, 150, 236, 110, 205, 236,
85, 141, 255, 37, 128, 27, 32, 11, 88, 7, 122, 130, 163, 33, 185, 216,
114, 218, 165, 155, 59, 43, 83,
95, 125, 248, 33, 130, 152, 97, 170, 168, 127, 62, 160, 16, 120, 12,
34, 133, 217, 163, 26, 249, 203, 2,
215, 65, 158, 176, 104, 116, 46, 167, 92, 122, 185, 227, 50, 201, 213,
150, 223, 46, 216, 28, 90, 137, 251,
38, 195, 90, 209, 251, 28, 67, 73, 241, 246, 196, 70, 211, 114, 221,
229, 153,
};
void scramble(unsigned char *inout)
{
unsigned char *r = inout + 12;
unsigned char *s = yellowbook_scrambler;
unsigned int i;
for (i = 2340; i; i--) {
*r++ ^= *s++;
}
}
/* Calculate the P parities for the sector.
* The 43 P vectors of length 24 are combined with the GF8_P_COEFFS.
*/
void parity_p(unsigned char *sector)
{
int i, j;
unsigned char p0_msb, p1_msb;
unsigned char p0_lsb, p1_lsb;
unsigned char *p_msb_start, *p_lsb_start;
unsigned char *p_msb, *p_lsb;
unsigned char *coeffs0, *coeffs1;
unsigned char *p0, *p1;
unsigned char d;
unsigned short c;
p_lsb_start = sector + LEC_HEADER_OFFSET;
p_msb_start = sector + LEC_HEADER_OFFSET + 1;
p1 = sector + LEC_MODE1_P_PARITY_OFFSET;
p0 = sector + LEC_MODE1_P_PARITY_OFFSET + 2 * 43;
for (i = 0; i <= 42; i++) {
p_lsb = p_lsb_start;
p_msb = p_msb_start;
coeffs0 = gf8_p_coeffs[0];
coeffs1 = gf8_p_coeffs[1];
p0_lsb = p1_lsb = p0_msb = p1_msb = 0;
for (j = 0; j <= 23; j++) {
d = *p_lsb;
if (d != 0) {
c = gf8_log[d] + *coeffs0;
if (c >= 255)
c -= 255;
p0_lsb ^= gf8_ilog[c];
c = gf8_log[d] + *coeffs1;
if (c >= 255)
c -= 255;
p1_lsb ^= gf8_ilog[c];
}
d = *p_msb;
if (d != 0) {
c = gf8_log[d] + *coeffs0;
if (c >= 255)
c -= 255;
p0_msb ^= gf8_ilog[c];
c = gf8_log[d] + *coeffs1;
if (c >= 255)
c -= 255;
p1_msb ^= gf8_ilog[c];
}
coeffs0++;
coeffs1++;
p_lsb += 2 * 43;
p_msb += 2 * 43;
}
*p0 = p0_lsb;
*(p0 + 1) = p0_msb;
*p1 = p1_lsb;
*(p1 + 1) = p1_msb;
p0 += 2;
p1 += 2;
p_lsb_start += 2;
p_msb_start += 2;
}
}
/* Calculate the Q parities for the sector.
* The 26 Q vectors of length 43 are combined with the GF8_Q_COEFFS.
*/
void parity_q(unsigned char *sector)
{
int i, j;
unsigned char q0_msb, q1_msb;
unsigned char q0_lsb, q1_lsb;
unsigned char *q_msb_start, *q_lsb_start;
unsigned char *q_msb, *q_lsb;
unsigned char *coeffs0, *coeffs1;
unsigned char *q0, *q1, *q_start;
unsigned char d;
unsigned short c;
q_lsb_start = sector + LEC_HEADER_OFFSET;
q_msb_start = sector + LEC_HEADER_OFFSET + 1;
q_start = sector + LEC_MODE1_Q_PARITY_OFFSET;
q1 = sector + LEC_MODE1_Q_PARITY_OFFSET;
q0 = sector + LEC_MODE1_Q_PARITY_OFFSET + 2 * 26;
for (i = 0; i <= 25; i++) {
q_lsb = q_lsb_start;
q_msb = q_msb_start;
coeffs0 = gf8_q_coeffs[0];
coeffs1 = gf8_q_coeffs[1];
q0_lsb = q1_lsb = q0_msb = q1_msb = 0;
for (j = 0; j <= 42; j++) {
d = *q_lsb;
if (d != 0) {
c = gf8_log[d] + *coeffs0;
if (c >= 255)
c -= 255;
q0_lsb ^= gf8_ilog[c];
c = gf8_log[d] + *coeffs1;
if (c >= 255)
c -= 255;
q1_lsb ^= gf8_ilog[c];
}
d = *q_msb;
if (d != 0) {
c = gf8_log[d] + *coeffs0;
if (c >= 255)
c -= 255;
q0_msb ^= gf8_ilog[c];
c = gf8_log[d] + *coeffs1;
if (c >= 255)
c -= 255;
q1_msb ^= gf8_ilog[c];
}
coeffs0++;
coeffs1++;
q_lsb += 2 * 44;
q_msb += 2 * 44;
if (q_lsb >= q_start) {
q_msb -= 2 * 1118;
q_lsb -= 2 * 1118;
}
}
*q0 = q0_lsb;
*(q0 + 1) = q0_msb;
*q1 = q1_lsb;
*(q1 + 1) = q1_msb;
q0 += 2;
q1 += 2;
q_lsb_start += 2 * 43;
q_msb_start += 2 * 43;
}
}

View File

@ -1,12 +0,0 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
#ifndef __LEC
#define __LEC
#define RS_L12_BITS 8
void scramble(unsigned char *);
void parity_p(unsigned char *in);
void parity_q(unsigned char *in);
#endif /* __LEC */

View File

@ -1,13 +1,28 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
This is the official API definition of libburn.
*/
#ifndef LIBBURN_H
#define LIBBURN_H
/* Needed for off_t which is the (POSIX-ly) appropriate type for
expressing a file or stream size.
/*
Applications must use 64 bit off_t. E.g. by defining
#define _LARGEFILE_SOURCE
#define _FILE_OFFSET_BITS 64
or take special precautions to interface with the library by 64 bit integers
where this .h files prescribe off_t.
To prevent 64 bit file i/o in the library would keep the application from
processing tracks of more than 2 GB size.
XXX we should enforce 64-bitness for off_t
ts A61101 : this is usually done by the build system (if it is not broken)
*/
#include <sys/types.h>
@ -115,7 +130,8 @@ enum burn_write_types
2s gaps between tracks, no fonky lead-ins
With sequential DVD-R[W]: Incremental Streaming
With DVD-RAM/+RW: Random Writeable (used sequentially)
With DVD+R and BD-R: Track of open size
With DVD-RAM, DVD+RW, BD-RE: Random Writeable (used sequentially)
With overwriteable DVD-RW: Rigid Restricted Overwrite
*/
BURN_WRITE_TAO,
@ -126,19 +142,32 @@ enum burn_write_types
With sequential DVD-R[W]: Disc-at-once, DAO
Single session, single track, fixed size mandatory, (-dvd-compat)
With other DVD or BD media: same as BURN_WRITE_TAO but may demand
that track size is known in advance.
*/
BURN_WRITE_SAO,
/** With CD: Raw disc at once recording.
all subcodes must be provided by lib or user
only raw block types are supported
With DVD and BD media: not supported.
ts A90901: This had been disabled because its implementation
relied on code from cdrdao which is not understood
currently.
A burn run will abort with "FATAL" error message
if this mode is attempted.
@since 0.7.2
ts A91016: Re-implemented according to ECMA-130 Annex A and B.
Now understood, explained and not stemming from cdrdao.
@since 0.7.4
*/
BURN_WRITE_RAW,
/** In replies this indicates that not any writing will work.
As parameter for inquiries it indicates that no particular write
mode shall is specified.
Do not use for setting a write mode for burning. It won't work.
Do not use for setting a write mode for burning. It will not work.
*/
BURN_WRITE_NONE
};
@ -183,18 +212,41 @@ enum burn_block_types
BURN_BLOCK_SAO = 16384
};
/** Possible status' of the drive in regard to the disc in it. */
/** Possible status of the drive in regard to the disc in it. */
enum burn_disc_status
{
/** The current status is not yet known */
BURN_DISC_UNREADY,
/** The drive holds a blank disc */
/** The drive holds a blank disc. It is ready for writing from scratch.
Unused multi-session media:
CD-R, CD-RW, DVD-R, DVD-RW, DVD+R, BD-R
Blanked multi-session media (i.e. treated by burn_disc_erase())
CD-RW, DVD-RW
Overwriteable media with or without valid data
DVD-RAM, DVD+RW, formatted DVD-RW, BD-RE
*/
BURN_DISC_BLANK,
/** There is no disc at all in the drive */
BURN_DISC_EMPTY,
/** There is an incomplete disc in the drive */
/** There is an incomplete disc in the drive. It is ready for appending
another session.
Written but not yet closed multi-session media
CD-R, CD-RW, DVD-R, DVD-RW, DVD+R, BD-R
*/
BURN_DISC_APPENDABLE,
/** There is a disc with data on it in the drive */
/** There is a disc with data on it in the drive. It is usable only for
reading.
Written and closed multi-session media
CD-R, CD-RW, DVD-R, DVD-RW, DVD+R, BD-R
Read-Only media
CD-ROM, DVD-ROM, BD-ROM
Note that many DVD-ROM drives report any written media
as Read-Only media and not by their real media types.
*/
BURN_DISC_FULL,
/* ts A61007 */
@ -204,7 +256,7 @@ enum burn_disc_status
/* ts A61020 */
/* @since 0.2.6 */
/** The media seems not to be suitable for burning */
/** The media seems to be unsuitable for reading and for writing */
BURN_DISC_UNSUITABLE
};
@ -311,7 +363,7 @@ struct burn_toc_entry
*/
unsigned char extensions_valid;
/* ts A70201 : DVD extension.
/* ts A70201 : DVD extension. extensions_valid:bit0
If invalid the members are guaranteed to be 0. */
/* @since 0.3.2 */
/* Tracks and session numbers are 16 bit. Here are the high bytes. */
@ -322,6 +374,13 @@ struct burn_toc_entry
/* min, sec, and frame may be too small if DVD extension is valid */
int track_blocks;
/* ts A90909 : LRA extension. extensions_valid:bit1 */
/* @since 0.7.2 */
/* MMC-5 6.27.3.18 : The Last Recorded Address is valid for DVD-R,
DVD-R DL when LJRS = 00b, DVD-RW, HD DVD-R, and BD-R.
This would mean profiles: 0x11, 0x15, 0x13, 0x14, 0x51, 0x41, 0x42
*/
int last_recorded_address;
};
@ -384,6 +443,13 @@ struct burn_source {
The size of a sector depends on BURN_MODE_*. The known range is
2048 to 2352.
If this call is reading from a pipe then it will learn
about the end of data only when that pipe gets closed on the
feeder side. So if the track size is not fixed or if the pipe
delivers less than the predicted amount or if the size is not
block aligned, then burning will halt until the input process
closes the pipe.
IMPORTANT:
If this function pointer is NULL, then the struct burn_source is of
version >= 1 and the job of .(*read)() is done by .(*read_xt)().
@ -670,17 +736,22 @@ void burn_finish(void);
/* ts A61002 */
/** Abort any running drive operation and finally call burn_finish().
You MUST calm down the busy drive if an aborting event occurs during a
/** Abort any running drive operation and eventually call burn_finish().
You MUST shut down the busy drives if an aborting event occurs during a
burn run. For that you may call this function either from your own signal
handling code or indirectly by activating the builtin signal handling:
handling code or indirectly by activating the built-in signal handling:
burn_set_signal_handling("my_app_name : ", NULL, 0);
Else you may eventually call burn_drive_cancel() on the active drive and
wait for it to assume state BURN_DRIVE_IDLE.
@param patience Maximum number of seconds to wait for drives to finish
Else you may eventually call burn_drive_cancel() on the active drives and
wait for them to assume state BURN_DRIVE_IDLE.
@param patience Maximum number of seconds to wait for drives to
finish.
@since 0.7.8 :
If this is -1, then only the cancel operations will
be performed and no burn_finish() will happen.
@param pacifier_func If not NULL: a function to produce appeasing messages.
See burn_abort_pacifier() for an example.
@param handle Opaque handle to be used with pacifier_func
@param handle Opaque handle to be used with pacifier_func
@return 1 ok, all went well
0 had to leave a drive in unclean state
<0 severe error, do no use libburn again
@ -707,17 +778,29 @@ int burn_abort_pacifier(void *handle, int patience, int elapsed);
*/
void burn_set_verbosity(int level);
/* ts A91111 */
/** Enable resp. disable logging of SCSI commands (currently GNU/Linux only).
This call can be made at any time - even before burn_initialize().
It is in effect for all active drives and currently not very thread
safe for multiple drives.
@param flag Bitfield for control purposes. The default is 0.
bit0= log to file /tmp/libburn_sg_command_log
bit1= log to stderr
bit2= flush output after each line
@since 0.7.4
*/
void burn_set_scsi_logging(int flag);
/* ts A60813 */
/** Set parameters for behavior on opening device files. To be called early
after burn_initialize() and before any bus scan. But not mandatory at all.
Parameter value 1 enables a feature, 0 disables.
Default is (1,0,0). Have a good reason before you change it.
@param exclusive Linux only:
@param exclusive
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)
There are kernels which simply don't care about O_EXCL.
Some have it off, some have it on, some are switchable.
and try to mark them busy if opened sucessfully. (O_EXCL
on GNU/Linux , flock(LOCK_EX) on FreeBSD.)
2 = in case of a SCSI device, also try to open exclusively
the matching /dev/sr, /dev/scd and /dev/st .
One may select a device SCSI file family by adding
@ -726,8 +809,8 @@ void burn_set_verbosity(int level);
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.
Add 32 to demand on GNU/Linux an exclusive lock by
fcntl(,F_SETLK,) after open() has succeeded.
@param blocking Try to wait for drives which do not open immediately but
also do not return an error as well. (O_NONBLOCK)
This might stall indefinitely with /dev/hdX hard disks.
@ -797,12 +880,12 @@ void burn_allow_untested_profiles(int yes);
If the path leads to an existing file of any type other than directory,
then the result is a sequential write-only stdio-drive = drive role 3.
The special address form "stdio:/dev/fd/<number>" is interpreted literally
as reference to open file descriptor <number>. This address form coincides
The special address form "stdio:/dev/fd/{number}" is interpreted literally
as reference to open file descriptor {number}. This address form coincides
with real files on some systems, but it is in fact hardcoded in libburn.
Special address "stdio:-" means stdout = "stdio:/dev/fd/1".
The role of such a drive is determined by the file type obtained via
fstat(<number>).
fstat({number}).
Roles 2 and 3 perform all their eventual data transfer activities on a file
via standard i/o functions open(2), lseek(2), read(2), write(2), close(2).
@ -813,7 +896,8 @@ void burn_allow_untested_profiles(int yes);
If the path does not exist in the filesystem yet, it is attempted to create
it as a regular file as soon as write operations are started.
The capabilities of role 3 resemble a blank DVD-R.
The capabilities of role 3 resemble a blank DVD-R. Nevertheless each
burn_disc_write() run may only write a single track.
One may distinguish pseudo-drives from MMC drives by call
burn_drive_get_drive_role().
@ -993,10 +1077,39 @@ int burn_drive_obtain_scsi_adr(char *path, int *bus_no, int *host_no,
*/
int burn_drive_grab(struct burn_drive *drive, int load);
/* ts B00114 */
/* Probe available CD write modes and block types. In earlier versions this
was done unconditionally on drive examination or aquiration. But it is
lengthy and obtrusive, up to spoiling burn runs on the examined drives.
So now this probing is omitted by default. All drives which announce to be
capable of CD or DVD writing, get blindly attributed the capability for
SAO and TAO. Applications which are interested in RAW modes or want to
rely on the traditional write mode information, may use this call.
@param drive_info drive object to be inquired
@return >0 indicates success, <=0 means failure
@since 0.7.6
*/
int burn_drive_probe_cd_write_modes(struct burn_drive_info *drive_info);
/* ts A90824 */
/** Calm down or alert a drive. Some drives stay alert after reading for
quite some time. This saves time with the startup for the next read
operation but also causes noise and consumes extra energy. It makes
sense to calm down the drive if no read operation is expected for the
next few seconds. The drive will get alert automatically if operations
are required.
@param d The drive to influence.
@param flag Bitfield for control purposes
bit0= become alert (else start snoozing)
This is not mandatory to allow further drive operations
@return 1= success , 0= drive role not suitable for calming
@since 0.7.0
*/
int burn_drive_snooze(struct burn_drive *d, int flag);
/** Release a drive. This should not be done until the drive is no longer
busy (see burn_drive_get_status).
Linux: The drive device file is not reserved afterwards. (O_EXCL, F_SETLK).
@param drive The drive to release.
@param eject Nonzero to make the drive eject the disc in it.
*/
@ -1008,7 +1121,7 @@ void burn_drive_release(struct burn_drive *drive, int eject);
eject button disabled. This physically locked drive state will last until
the drive is grabbed again and released via burn_drive_release().
Programs like eject, cdrecord, growisofs will break that ban too.
@param drive The drive to release and leave locked.
@param d The drive to release and leave locked.
@param flag Bitfield for control purposes (unused yet, submit 0)
@return 1 means success, <=0 means failure
@since 0.4.0
@ -1073,6 +1186,61 @@ int burn_disc_read_atip(struct burn_drive *drive);
int burn_drive_get_start_end_lba(struct burn_drive *drive,
int *start_lba, int *end_lba, int flag);
/* ts A90902 */
/** Guess the manufacturer name of CD media from the ATIP addresses of lead-in
and lead-out. (Currently only lead-in is interpreted. Lead-out may in
future be used to identify the media type in more detail.)
The parameters of this call should be obtained by burn_disc_read_atip(d),
burn_drive_get_start_end_lba(d, &start_lba, &end_lba, 0),
burn_lba_to_msf(start_lba, &m_li, &s_li, &f_li) and
burn_lba_to_msf(end_lba, &m_lo, &s_lo, &f_lo).
@param m_li "minute" part of ATIP lead-in resp. start_lba
@param s_li "second" of lead-in resp. start_lba
@param f_li "frame" of lead-in
@param m_lo "minute" part of ATIP lead-out
@param s_lo "second" of lead-out
@param f_lo "frame" of lead-out
@param flag Bitfield for control purposes,
bit0= append a text "(aka ...)" to reply if other brands or
vendor names are known.
@return Printable text or NULL on memory shortage.
Dispose by free() when no longer needed.
@since 0.7.2
*/
char *burn_guess_cd_manufacturer(int m_li, int s_li, int f_li,
int m_lo, int s_lo, int f_lo, int flag);
/* ts A90909 */
/** Retrieve some media information which is mainly specific to CD. For other
media only the bits in reply parameter valid are supposed to be meaningful.
@param d The drive to query.
@param disc_type A string saying either "CD-DA or CD-ROM", or "CD-I",
or ""CD-ROM XA", or "undefined".
@param disc_id A 32 bit number read from the media. (Meaning unclear yet)
@param bar_code 8 hex digits from a barcode on media read by the drive
(if the drive has a bar code reader built in).
@param app_code The Host Application Code which must be set in the Write
Parameters Page if the media is not unrestricted (URU==0).
@param valid Replies bits which indicate the validity of other reply
parameters or the state of certain CD info bits:
bit0= disc_type is valid
bit1= disc_id is valid
bit2= bar_code is valid
bit3= disc_app_code is valid
bit4= Disc is unrestricted (URU bit, 51h READ DISC INFO)
This seems to be broken with my drives. The bit is
0 and the validity bit for disc_app_code is 0 too.
bit5= Disc is nominally erasable (Erasable bit)
This will be set with overwriteable media which
libburn normally considers to be unerasable blank.
@since 0.7.2
*/
int burn_disc_get_cd_info(struct burn_drive *d, char disc_type[80],
unsigned int *disc_id, char bar_code[9], int *app_code,
int *valid);
/* ts A61110 */
/** Read start lba and Next Writeable Address of a track from media.
Usually a track lba is obtained from the result of burn_track_get_entry().
@ -1129,7 +1297,8 @@ off_t burn_disc_available_space(struct burn_drive *d,
0x11 "DVD-R sequential recording", 0x12 "DVD-RAM",
0x13 "DVD-RW restricted overwrite", 0x14 "DVD-RW sequential recording",
0x1a "DVD+RW", 0x1b "DVD+R",
0x2b "DVD+R/DL", 0x43 "BD-RE",
0x2b "DVD+R/DL",
0x41 "BD-R sequential recording", 0x43 "BD-RE",
0xffff "stdio file"
Note: 0xffff is not a MMC profile but a libburn invention.
If enabled by burn_allow_untested_profiles() it also writes to profiles
@ -1137,8 +1306,8 @@ off_t burn_disc_available_space(struct burn_drive *d,
Read-only are the profiles
0x08 "CD-ROM", 0x10 "DVD-ROM",
0x40 "BD-ROM",
For now read-only are BD-R profiles (testers wanted)
0x41 "BD-R sequential recording", 0x42 "BD-R random recording"
For now read-only is BD-R profile (testers wanted)
0x42 "BD-R random recording"
@param d The drive where the media is inserted.
@param pno Profile Number. See also mmc5r03c.pdf, table 89
@param name Profile Name (see above list, unknown profiles have empty name)
@ -1147,6 +1316,59 @@ off_t burn_disc_available_space(struct burn_drive *d,
*/
int burn_disc_get_profile(struct burn_drive *d, int *pno, char name[80]);
/* ts A90903 : API */
/** Obtain product id and standards defined media codes.
The product id is a printable string which is supposed to be the same
for identical media but should vary with non-identical media. Some media
do not allow to obtain such an id at all.
The pair (profile_number, product_id) should be the best id to identify
media with identical product specifications.
The reply parameters media_code1 and media_code2 can be used with
burn_guess_manufacturer()
The reply parameters have to be disposed by free() when no longer needed.
@param d The drive where the media is inserted.
@param product_id Reply: Printable text depicting manufacturer and
eventually media id.
@param media_code1 Reply: The eventual manufacturer identification as read
from DVD/BD media or a text "XXmYYsZZf" from CD media
ATIP lead-in.
@param media_code2 The eventual media id as read from DVD+/BD media or a
text "XXmYYsZZf" from CD ATIP lead-out.
@param book_type Book type text for DVD and BD.
Caution: is NULL with CD, even if return value says ok.
@param flag Bitfield for control purposes
bit0= do not escape " _/" (not suitable for
burn_guess_manufacturer())
@return 1= ok, product_id and media codes are valid,
0= no product id_available, reply parameters are NULL
<0= error
@since 0.7.2
*/
int burn_disc_get_media_id(struct burn_drive *d,
char **product_id, char **media_code1, char **media_code2,
char **book_type, int flag);
/* ts A90904 */
/** Guess the name of a manufacturer by profile number, manufacturer code
and media code. The profile number can be obtained by
burn_disc_get_profile(), the other two parameters can be obtained as
media_code1 and media_code2 by burn_get_media_product_id().
@param profile_no Profile number (submit -1 if not known)
@param manuf_code Manufacturer code from media (e.g. "RICOHJPN")
@param media_code Media ID code from media (e.g. "W11")
@param flag Bitfield for control purposes, submit 0
@return Printable text or NULL on memory shortage.
If the text begins with "Unknown " then no item of the
manufacturer list matched the codes.
Dispose by free() when no longer needed.
@since 0.7.2
*/
char *burn_guess_manufacturer(int profile_no,
char *manuf_code, char *media_code, int flag);
/** Tells whether a disc can be erased or not
@param d The drive to inquire.
@return Non-zero means erasable
@ -1161,8 +1383,8 @@ int burn_disc_erasable(struct burn_drive *d);
enum burn_drive_status burn_drive_get_status(struct burn_drive *drive,
struct burn_progress *p);
/** Creates a write_opts struct for burning to the specified drive
must be freed with burn_write_opts_free
/** Creates a write_opts struct for burning to the specified drive.
The returned object must later be freed with burn_write_opts_free().
@param drive The drive to write with
@return The write_opts, NULL on error
*/
@ -1212,7 +1434,8 @@ void burn_disc_erase(struct burn_drive *drive, int fast);
/** Format media for use with libburn. This currently applies to DVD-RW
in state "Sequential Recording" (profile 0014h) which get formatted to
state "Restricted Overwrite" (profile 0013h). DVD+RW can be "de-iced"
by setting bit2 of flag. Other media cannot be formatted yet.
by setting bit2 of flag. DVD-RAM and BD-RE may get formatted initially
or re-formatted to adjust their Defect Managment.
This function usually returns while the drive is still in the process
of formatting. The formatting is done, when burn_drive_get_status()
returns BURN_DRIVE_IDLE. This may be immediately after return or may
@ -1227,7 +1450,8 @@ void burn_disc_erase(struct burn_drive *drive, int fast);
bit1+2: size mode
0 = use parameter size as far as it makes sense
1 = insist in size 0 even if there is a better default known
(on DVD-RAM or BD-RE identical to size mode 0)
(on DVD-RAM or BD-R identical to size mode 0,
i.e. they never get formatted with payload size 0)
2 = without bit7: format to maximum available size
with bit7 : take size from indexed format descriptor
3 = without bit7: format to default size
@ -1236,13 +1460,16 @@ void burn_disc_erase(struct burn_drive *drive, int fast);
bit4= enforce re-format of (partly) formatted media
bit5= try to disable eventual defect management
bit6= try to avoid lengthy media certification
bit7= MMC expert application mode (else libburn tries to
choose a suitable format type):
bit8 to bit15 contain the index of the format to use. See
burn_disc_get_formats(), burn_disc_get_format_descr().
bit7, bit8 to bit15 =
bit7 enables MMC expert application mode (else libburn
tries to choose a suitable format type):
If it is set then bit8 to bit15 contain the index of
the format to use. See burn_disc_get_formats(),
burn_disc_get_format_descr().
Acceptable types are: 0x00, 0x01, 0x10, 0x11, 0x13,
0x15, 0x26, 0x30, 0x31.
If bit7 is set, bit4 is set automatically.
0x15, 0x26, 0x30, 0x31, 0x32.
If bit7 is set, then bit4 is set automatically.
bit16= enable POW on blank BD-R
@since 0.3.0
*/
void burn_disc_format(struct burn_drive *drive, off_t size, int flag);
@ -1347,6 +1574,28 @@ int burn_precheck_write(struct burn_write_opts *o, struct burn_disc *disc,
*/
void burn_disc_write(struct burn_write_opts *o, struct burn_disc *disc);
/* ts A90227 */
/** Control stream recording during the write run and eventually set the start
LBA for stream recording.
Stream recording is set from struct burn_write_opts when the write run
gets started. See burn_write_opts_set_stream_recording().
The call described here can be used later to override this setting and
to program automatic switching at a given LBA. It also affects subsequent
calls to burn_random_access_write().
@param drive The drive which performs the write operation.
@param recmode -1= disable stream recording
0= leave setting as is
1= enable stream recording
@param start The LBA where actual stream recording shall start.
(0 means unconditional stream recording)
@param flag Bitfield for control purposes (unused yet, submit 0).
@return 1=success , <=0 failure
@since 0.6.4
*/
int burn_drive_set_stream_recording(struct burn_drive *drive, int recmode,
int start, int flag);
/** Cancel an operation on a drive.
This will only work when the drive's busy state is BURN_DRIVE_READING or
BURN_DRIVE_WRITING.
@ -1356,9 +1605,11 @@ void burn_drive_cancel(struct burn_drive *drive);
/* ts A61223 */
/** Inquire whether the most recent write run was successful. Reasons for
non-success may be: rejection of burn parameters, abort during fatal errors
during write, a call to burn_drive_cancel() by the application thread.
/** Inquire whether the most recent asynchronous media job was successful.
This applies to burn_disc_erase(), burn_disc_format(), burn_disc_write().
Reasons for non-success may be: rejection of burn parameters, abort due to
fatal errors during write, blank or format, a call to burn_drive_cancel()
by the application thread.
@param d The drive to inquire.
@return 1=burn seems to have went well, 0=burn failed
@since 0.2.6
@ -1483,6 +1734,22 @@ void burn_track_define_data(struct burn_track *t, int offset, int tail,
int burn_track_set_byte_swap(struct burn_track *t, int swap_source_bytes);
/* ts A90910 */
/** Activates CD XA compatibility modes.
libburn currently writes data only in CD mode 1. Some programs insist in
sending data with additional management bytes. These bytes have to be
stripped in order to make the input suitable for BURN_MODE1.
@param t The track to manipulate
@param value 0= no conversion
1= strip 8 byte sector headers of CD-ROM XA mode 2 form 1
see MMC-5 4.2.3.8.5.3 Block Format for Mode 2 form 1 Data
all other values are reserved
@return 1=success , 0=unacceptable value
@since 0.7.2
*/
int burn_track_set_cdxa_conv(struct burn_track *t, int value);
/** Set the ISRC details for a track
@param t The track to change
@param country the 2 char country code. Each character must be
@ -1550,6 +1817,58 @@ void burn_source_free(struct burn_source *s);
struct burn_source *burn_file_source_new(const char *path,
const char *subpath);
/* ts A91122 : An interface to open(O_DIRECT) or similar OS tricks. */
/** Opens a file with eventual acceleration preparations which may depend
on the operating system and on compile time options of libburn.
You may use this call instead of open(2) for opening file descriptors
which shall be handed to burn_fd_source_new().
This should only be done for tracks with BURN_BLOCK_MODE1 (2048 bytes
per block).
If you use this call then you MUST allocate the buffers which you use
with read(2) by call burn_os_alloc_buffer(). Read sizes MUST be a multiple
of a safe buffer amount. Else you risk that track data get altered during
transmission.
burn_disk_write() will allocate a suitable read/write buffer for its own
operations. A fifo created by burn_fifo_source_new() will allocate
suitable memory for its buffer if called with flag bit0 and a multiple
of a safe buffer amount.
@param path The file address to open
@param open_flags The flags as of man 2 open. Normally just O_RDONLY.
@param flag Bitfield for control purposes (unused yet, submit 0).
@return A file descriptor as of open(2). Finally to be disposed
by close(2).
-1 indicates failure.
@since 0.7.4
*/
int burn_os_open_track_src(char *path, int open_flags, int flag);
/** Allocate a memory area that is suitable for reading with a file descriptor
opened by burn_os_open_track_src().
@param amount Number of bytes to allocate. This should be a multiple
of the operating system's i/o block size. 32 KB is
guaranteed by libburn to be safe.
@param flag Bitfield for control purposes (unused yet, submit 0).
@return The address of the allocated memory, or NULL on failure.
A non-NULL return value has finally to be disposed via
burn_os_free_buffer().
@since 0.7.4
*/
void *burn_os_alloc_buffer(size_t amount, int flag);
/** Dispose a memory area which was obtained by burn_os_alloc_buffer(),
@param buffer Memory address to be freed.
@param amount The number of bytes which was allocated at that
address.
@param flag Bitfield for control purposes (unused yet, submit 0).
@return 1 success , <=0 failure
@since 0.7.4
*/
int burn_os_free_buffer(void *buffer, size_t amount, int flag);
/** Creates a data source for an image file (a track) from an open
readable filedescriptor, an eventually open readable subcodes file
descriptor and eventually a fixed size in bytes.
@ -1579,14 +1898,26 @@ struct burn_source *burn_fd_source_new(int datafd, int subfd, off_t size);
@param inp The burn_source for which the fifo shall act as proxy.
It can be disposed by burn_source_free() immediately
after this call.
@param chunksize The size in bytes of a chunk. Use 2048 for sources
suitable for BURN_BLOCK_MODE1 and 2352 for sources
which deliver for BURN_BLOCK_AUDIO.
@param chunksize The size in bytes of a chunk.
Use 2048 for sources suitable for BURN_BLOCK_MODE1,
2352 for sources which deliver for BURN_BLOCK_AUDIO,
2056 for sources which shall get treated by
burn_track_set_cdxa_conv(track, 1).
Some variations of burn_source might work only with
a particular chunksize. E.g. libisofs demands 2048.
@param chunks The number of chunks to be allocated in ring buffer.
This value must be >= 2.
@param flag Bitfield for control purposes (unused yet, submit 0).
@param flag Bitfield for control purposes:
bit0= The read method of inp is capable of delivering
arbitrary amounts of data per call. Not only one
sector.
Suitable for inp from burn_file_source_new()
and burn_fd_source_new() if not the fd has
exotic limitations on read size.
You MUST use this on inp which uses an fd opened
with burn_os_open_track_src().
Better do not use with other inp types.
@since 0.7.4
@return A pointer to the newly created burn_source.
Later both burn_sources, inp and the returned fifo, have
to be disposed by calling burn_source_free() for each.
@ -1619,12 +1950,42 @@ struct burn_source *burn_fifo_source_new(struct burn_source *inp,
int burn_fifo_inquire_status(struct burn_source *fifo, int *size,
int *free_bytes, char **status_text);
/* ts A91125 */
/** Inquire various counters which reflect the fifo operation.
@param fifo The fifo object to inquire
@param total_min_fill The minimum number of bytes in the fifo. Beginning
from the moment when fifo consumption is enabled.
@param interval_min_fill The minimum byte number beginning from the moment
when fifo consumption is enabled or from the
most recent moment when burn_fifo_next_interval()
was called.
@param put_counter The number of data transactions into the fifo.
@param get_counter The number of data transactions out of the fifo.
@param empty_counter The number of times the fifo was empty.
@param full_counter The number of times the fifo was full.
@since 0.7.4
*/
void burn_fifo_get_statistics(struct burn_source *fifo,
int *total_min_fill, int *interval_min_fill,
int *put_counter, int *get_counter,
int *empty_counter, int *full_counter);
/* ts A91125 */
/** Inquire the fifo minimum fill counter for intervals and reset that counter.
@param fifo The fifo object to inquire
@param interval_min_fill The minimum number of bytes in the fifo. Beginning
from the moment when fifo consumption is enabled
or from the most recent moment when
burn_fifo_next_interval() was called.
@since 0.7.4
*/
void burn_fifo_next_interval(struct burn_source *fifo, int *interval_min_fill);
/* ts A80713 */
/** Obtain a preview of the first input data of a fifo which was created
by burn_fifo_source_new(). The data will later be delivered normally to
the consumer track of the fifo.
bufsize may not be larger than the fifo size (chunk_size * chunks).
bufsize may not be larger than the fifo size (chunk_size * chunks) - 32k.
This call will succeed only if data consumption by the track has not
started yet, i.e. best before the call to burn_disc_write().
It will start the worker thread of the fifo with the expectable side
@ -1632,17 +1993,33 @@ int burn_fifo_inquire_status(struct burn_source *fifo, int *size,
data have arrived or until it becomes clear that this will not happen.
The call may be repeated with increased bufsize. It will always yield
the bytes beginning from the first one in the fifo.
@param fifo The fifo object to inquire
@param fifo The fifo object to inquire resp. start
@param buf Pointer to memory of at least bufsize bytes where to
deliver the peeked data
deliver the peeked data.
@param bufsize Number of bytes to peek from the start of the fifo data
@param flag Bitfield for control purposes (unused yet, submit 0).
@return <0 on severe error, 0 if not enough data, 1 if bufsize bytes read
@since 0.5.0
*/
int burn_fifo_peek_data(struct burn_source *source, char *buf, int bufsize,
int burn_fifo_peek_data(struct burn_source *fifo, char *buf, int bufsize,
int flag);
/* ts A91125 */
/** Start the fifo worker thread and wait either until the requested number
of bytes have arrived or until it becomes clear that this will not happen.
Filling will go on asynchronously after burn_fifo_fill() returned.
This call and burn_fifo_peek_data() do not disturb each other.
@param fifo The fifo object to start
@param fill Number of bytes desired. Expect to get return 1 if
at least fifo size - 32k were read.
@param flag Bitfield for control purposes.
bit0= fill fifo to maximum size
@return <0 on severe error, 0 if not enough data,
1 if desired amount or fifo full
@since 0.7.4
*/
int burn_fifo_fill(struct burn_source *fifo, int fill, int flag);
/* ts A70328 */
/** Sets a fixed track size after the data source object has already been
@ -1865,17 +2242,46 @@ void burn_write_opts_set_force(struct burn_write_opts *opts, int use_force);
/* ts A80412 */
/** Eventually makes use of the more modern write command AAh WRITE12 and
sets the Streaming bit. With DVD-RAM this can override the traditional
slowdown to half nominal speed. But if it speeds up writing then it also
disables error management and correction. Weigh your priorities.
This only affects the write operations of burn_disc_write().
sets the Streaming bit. With DVD-RAM and BD this can override the
traditional slowdown to half nominal speed. But if it speeds up writing
then it also disables error management and correction. Weigh your
priorities. This affects the write operations of burn_disc_write()
and subsequent calls of burn_random_access_write().
@param opts The write opts to change
@param value 0=use 2Ah WRITE10, 1=use AAh WRITE12 with Streaming bit
@since 0.6.4:
>=16 use WRITE12 but not before the LBA given by value
@since 0.4.6
*/
void burn_write_opts_set_stream_recording(struct burn_write_opts *opts,
int value);
/* ts A91115 */
/** Overrides the write chunk size for DVD and BD media which is normally
determined according to media type and setting of stream recording.
A chunk size of 64 KB may improve throughput with bus systems which show
latency problems.
@param opts The write opts to change
@param obs Number of bytes which shall be sent by a single write command.
0 means automatic size, 32768 and 65336 are the only other
accepted sizes for now.
@since 0.7.4
*/
void burn_write_opts_set_dvd_obs(struct burn_write_opts *opts, int obs);
/* ts A91115 */
/** Sets the rythm by which stdio pseudo drives force their output data to
be consumed by the receiving storage device. This forcing keeps the memory
from being clogged with lots of pending data for slow devices.
@param opts The write opts to change
@param rythm Number of 2KB output blocks after which fsync(2) is
performed. -1 means no fsync(), 0 means default,
elsewise the value must be >= 32.
Default is currently 8192 = 16 MB.
@since 0.7.4
*/
void burn_write_opts_set_stdio_fsync(struct burn_write_opts *opts, int rythm);
/** Sets whether to read in raw mode or not
@param opts The read opts to change
@ -1932,6 +2338,34 @@ void burn_read_opts_transfer_damaged_blocks(struct burn_read_opts *opts,
void burn_read_opts_set_hardware_error_retries(struct burn_read_opts *opts,
unsigned char hardware_error_retries);
/* ts A90815 */
/** Gets the list of profile codes supported by the drive.
Profiles depict the feature sets which constitute media types. For
known profile codes and names see burn_disc_get_profile().
@param d is the drive to query
@param num_profiles returns the number of supported profiles
@param profiles returns the profile codes
@param is_current returns the status of the corresponding profile code:
1= current, i.e. the matching media is loaded
0= not current, i.e. the matching media is not loaded
@return always 1 for now
@since 0.7.0
*/
int burn_drive_get_all_profiles(struct burn_drive *d, int *num_profiles,
int profiles[64], char is_current[64]);
/* ts A90815 */
/** Obtains the profile name associated with a profile code.
@param profile_code the profile code to be translated
@param name returns the profile name (e.g. "DVD+RW")
@return 1= known profile code , 0= unknown profile code
@since 0.7.0
*/
int burn_obtain_profile_name(int profile_code, char name[80]);
/** Gets the maximum write speed for a drive and eventually loaded media.
The return value might change by the media type of already loaded media,
again by call burn_drive_grab() and again by call burn_disc_read_atip().
@ -2193,12 +2627,12 @@ void burn_version(int *major, int *minor, int *micro);
*/
#define burn_header_version_major 0
#define burn_header_version_minor 5
#define burn_header_version_micro 1
#define burn_header_version_minor 8
#define burn_header_version_micro 2
/** Note:
Above version numbers are also recorded in configure.ac because libtool
wants them as parameters at build time.
For the library compatibility check BURN_*_VERSION in configure.ac
For the library compatibility check, BURN_*_VERSION in configure.ac
are not decisive. Only the three numbers above do matter.
*/
/** Usage discussion:
@ -2244,6 +2678,15 @@ These two advises are mutually exclusive.
*/
/* ts A91226 */
/** Obtain the id string of the SCSI transport interface.
This interface may be a system specific adapter module of libburn or
an adapter to a supporting library like libcdio.
@flag Bitfield for control puposes, submit 0 for now
@return A pointer to the id string. Do not alter the string content.
@since 0.7.6
*/
char *burn_scsi_transport_id(int flag);
/* ts A60924 : ticket 74 */
/** Control queueing and stderr printing of messages from libburn.
@ -2346,30 +2789,82 @@ int burn_set_messenger(void *messenger);
/* ts A61002 */
/* @since 0.2.6 */
/** The prototype of a handler function suitable for burn_set_abort_handling().
/** The prototype of a handler function suitable for burn_set_signal_handling()
Such a function has to return -2 if it does not want the process to
exit with value 1.
*/
typedef int (*burn_abort_handler_t)(void *handle, int signum, int flag);
/** Control builtin signal handling. See also burn_abort().
/** Control built-in signal handling. Either by setting an own handler or
by activating the built-in signal handler.
A function parameter handle of NULL activates the built-in abort handler.
Depending on mode it may cancel all drive operations, wait for all drives
to become idle, exit(1). It may also prepare function
burn_drive_get_status() for waiting and performing exit(1).
If parameter handle may be NULL or a text that shall be used as prefix for
pacifier messages of burn_abort_pacifier(). Other than with an application
provided handler, the prefix char array does not have to be kept existing
until the eventual signal event.
Before version 0.7.8 only action 0 was available. I.e. the built-in handler
waited for the drives to become idle and then performed exit(1) directly.
But during burn_disc_write() onto real CD or DVD, FreeBSD 8.0 pauses the
other threads until the signal handler returns.
The new actions try to avoid this deadlock. It is advised to use action 3
at least during burn_disc_write(), burn_disc_rease(), burn_disc_format():
burn_set_signal_handling(text, NULL, 0x30);
and to call burn_is_aborting(0) when the drive is BURN_DRIVE_IDLE.
If burn_is_aborting(0) returns 1, then call burn_abort() and exit(1).
@param handle Opaque handle eventually pointing to an application
provided memory object
@param handler A function to be called on signals. It will get handle as
argument. It should finally call burn_abort(). See there.
@param mode : 0 call handler(handle, signum, 0) on nearly all signals
1 enable system default reaction on all signals
2 try to ignore nearly all signals
10 like mode 2 but handle SIGABRT like with mode 0
Arguments (text, NULL, 0) activate the builtin abort handler. It will
eventually call burn_abort() and then perform exit(1). If text is not NULL
then it is used as prefix for pacifier messages of burn_abort_pacifier().
argument. flag will be 0.
It should finally call burn_abort(). See there.
@param mode : bit0 - bit3:
Receiving signals:
0 Call handler(handle, signum, 0) on nearly all signals
1 Enable system default reaction on all signals
2 Try to ignore nearly all signals
10 like mode 2 but handle SIGABRT like with mode 0
bit4 - bit7: With handler == NULL :
Action of built-in handler. "control thread" is the one
which called burn_set_signal_handling().
All actions activate receive mode 2 to ignore further
signals.
0 Same as 1 (for pre-0.7.8 backward compatibility)
@since 0.7.8
1 Catch the control thread in abort handler, call
burn_abort(>0) and finally exit(1).
Does not always work with FreeBSD.
2 Call burn_abort(-1) and return from handler. When the
control thread calls burn_drive_get_status(), then do
burn_abort(>0) instead, and finally exit(1).
Does not always work with FreeBSD.
3 Call burn_abort(-1), return from handler. It is duty of
the application to detect a pending abort condition
by calling burn_is_aborting() and to wait for all
drives to become idle. E.g. by calling burn_abort(>0).
4 Like 3, but without calling burn_abort(-1). Only the
indicator of burn_is_aborting() gets set.
@since 0.2.6
*/
void burn_set_signal_handling(void *handle, burn_abort_handler_t handler,
int mode);
/* ts B00304 */
/* Inquire whether the built-in abort handler was triggered by a signal.
This has to be done to detect pending abort handling if signal handling
was set to the built-in handler and action was set to 2 or 3.
@param flag Bitfield for control purposes (unused yet, submit 0)
@return 0 = no abort was triggered
>0 = action that was triggered (action 0 is reported as 1)
@since 0.7.8
*/
int burn_is_aborting(int flag);
/* ts A70811 */
/** Write data in random access mode.
The drive must be grabbed successfully before calling this function which
@ -2403,6 +2898,21 @@ int burn_random_access_write(struct burn_drive *d, off_t byte_address,
char *data, off_t data_count, int flag);
/* ts A81215 */
/** Inquire the maximum amount of readable data.
It is supposed that all LBAs in the range from 0 to media_read_acpacity-1
can be read via burn_read_data() although some of them may never have been
recorded. If tracks are recognizable then it is better to only read
LBAs which are part of some track.
@param d The drive from which to read
@param capacity Will return the result if valid
@param flag Bitfield for control purposes: Unused yet, submit 0.
@return 1=sucessful , <=0 an error occured
@since 0.6.0
*/
int burn_get_read_capacity(struct burn_drive *d, int *capacity, int flag);
/* ts A70812 */
/** Read data in random access mode.
The drive must be grabbed successfully before calling this function.
@ -2412,7 +2922,7 @@ int burn_random_access_write(struct burn_drive *d, off_t byte_address,
This is a synchronous call which returns only after the full read job
has ended (sucessfully or not). So it is wise not to read giant amounts
of data in a single call.
@param d The drive to which to write
@param d The drive from which to read
@param byte_address The start address of the read in byte (aligned to 2048)
@param data A memory buffer capable of taking data_size bytes
@param data_size The amount of data to be read. This does not have to
@ -2470,11 +2980,36 @@ int burn_drive_get_drive_role(struct burn_drive *d);
int burn_drive_equals_adr(struct burn_drive *d1, char *adr2, int drive_role2);
#ifndef DOXYGEN
BURN_END_DECLS
#endif
/* ts A91205 */
/* The following experiments may be interesting in future:
*/
/* Perform OPC explicitely.
# define Libburn_pioneer_dvr_216d_with_opC 1
*/
/* Load mode page 5 and modify it rather than composing from scratch.
# define Libburn_pioneer_dvr_216d_load_mode5 1
*/
/* Inquire drive events and react by reading configuration or starting unit.
# define Libburn_pioneer_dvr_216d_get_evenT 1
*/
/* ts A91112 */
/* Do not probe CD modes but declare only data and audio modes supported.
For other modes resp. real probing one has to call
burn_drive_probe_cd_write_modes().
*/
#define Libburn_dummy_probe_write_modeS 1
#endif /*LIBBURN_H*/

View File

@ -1,9 +1,13 @@
/* libdax_audioxtr
Audio track data extraction facility of libdax and libburn.
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>

View File

@ -1,7 +1,7 @@
/* libdax_audioxtr
Audio track data extraction facility of libdax and libburn.
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
*/
#ifndef LIBDAX_AUDIOXTR_H_INCLUDED

View File

@ -1,10 +1,14 @@
/* libdax_msgs
Message handling facility of libdax.
Copyright (C) 2006 - 2008 Thomas Schmitt <scdbackup@gmx.net>,
provided under GPL version 2
Copyright (C) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>,
provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
@ -12,6 +16,7 @@
#include <stdlib.h>
#include <errno.h>
#include <sys/time.h>
#include <pthread.h>
/* Only this single source module is entitled to do this */
#define LIBDAX_MSGS_H_INTERNAL 1

View File

@ -1,8 +1,8 @@
/* libdax_msgs
Message handling facility of libdax.
Copyright (C) 2006-2008 Thomas Schmitt <scdbackup@gmx.net>,
provided under GPL version 2
Copyright (C) 2006-2010 Thomas Schmitt <scdbackup@gmx.net>,
provided under GPL version 2 or later.
*/
@ -434,6 +434,8 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
0x00020009 (SORRY,HIGH) = Neither stdio-path nor its directory exist
0x0002000a (FAILURE,HIGH) = Cannot accept '...' as SG_IO CDROM drive
0x0002000b (FAILURE,HIGH) = File object '...' not found
0x0002000c (FAILURE,HIGH) = Cannot start device file enumeration
0x0002000d (FAILURE,HIGH) = Cannot enumerate next device
General library operations:
@ -528,9 +530,35 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
0x00020159 (DEBUG,HIGH) = TOC Format 0 returns inconsistent data
0x0002015a (NOTE,HIGH) = Could not examine busy device
0x0002015b (HINT,HIGH) = Busy '...' seems to be a hard disk, as '...1' exists
0x0002015c (FAILURE,HIGH) = Fifo size is smaller than desired peek buffer
0x0002015c (FAILURE,HIGH) = Fifo size too small for desired peek buffer
0x0002015d (FAILURE,HIGH) = Fifo input ended short of desired peek buffer size
0x0002015e (FATAL,HIGH) = Fifo is already under consumption when peeking
0x0002015f (MISHAP,HIGH) = Damaged CD table-of-content detected and truncated
0x00020160 (WARNING,HIGH) = Session without leadout encountered
0x00020161 (WARNING,HIGH) = Empty session deleted
0x00020162 (SORRY,HIGH) = BD-R not unformatted blank any more. Cannot format
0x00020163 (NOTE,HIGH) = Blank BD-R left unformatted for zero spare capacity
0x00020164 (SORRY,HIGH) = Drive does not format BD-RE without spares
0x00020165 (WARNING,HIGH) = Drive does not support fast formatting
0x00020166 (WARNING,HIGH) = Drive does not support full formatting
0x00020167 (SORRY,HIGH) = Drive does not support non-default formatting
0x00020168 (FAILURE,HIGH) = Media not properly formatted. Cannot write.
0x00020169 (WARNING,HIGH) = Last session on media is still open
0x0002016a (FAILURE,HIGH) = No MMC transport adapter is present
0x0002016b (WARNING,HIGH) = No MMC transport adapter is present
0x0002016c (DEBUG,HIGH) = No MMC transport adapter is present
0x0002016e (DEBUG,HIGH) = MODE SENSE page 2A too short
0x0002016f (DEBUG,HIGH) = Unable to grab scanned drive
0x00020170 (NOTE,HIGH) = Closing open session before writing new one
0x00020171 (NOTE,HIGH) = Closing BD-R with accidently open session
0x00020172 (SORRY,HIGH) = Read start address larger than number of readable blocks
0x00020173 (FAILURE,HIGH) = Drive tells NWA smaller than last written address
0x00020174 (SORRY,HIGH) = Fifo alignment does not allow desired read size
0x00020175 (FATAL,HIGH) = Supporting library is too old
0x00020176 (NOTE,HIGH) = Stream recording disabled because of small OS buffer
0x00020177 (ABORT,HIGH) = Urged drive worker threads to do emergency halt
0x00020178 (DEBUG,HIGH) = Write thread ended
libdax_audioxtr:
0x00020200 (SORRY,HIGH) = Cannot open audio source file

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,11 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifndef __MMC
#define __MMC
@ -68,13 +74,37 @@ int mmc_compose_mode_page_5(struct burn_drive *d,
const struct burn_write_opts *o,
unsigned char *pd);
/* ts A70201 */
int mmc_four_char_to_int(unsigned char *data);
/* ts A70812 : return 0 = ok , return BE_CANCELLED = error occured */
int mmc_read_10(struct burn_drive *d, int start, int amount,
struct buffer *buf);
/* ts A81210 : Determine the upper limit of readable data size */
int mmc_read_capacity(struct burn_drive *d);
/* ts A61201 */
char *mmc_obtain_profile_name(int profile_number);
/* mmc5r03c.pdf 4.3.4.4.1 d) "The maximum number of RZones is 2 302." */
#define BURN_MMC_FAKE_TOC_MAX_SIZE 2302
/* ts A90903 */
/* MMC backend of API call burn_get_media_product_id()
*/
int mmc_get_media_product_id(struct burn_drive *d,
char **product_id, char **media_code1, char **media_code2,
char **book_type, int flag);
/* ts A60910 (estimated) */
int mmc_function_spy(struct burn_drive *d, char * text);
/* ts A91118 */
int mmc_start_if_needed(struct burn_drive *d, int flag);
#endif /*__MMC*/

View File

@ -1,5 +1,14 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include "null.h"
#include "libburn.h"
#include <stdlib.h>

View File

@ -1,3 +1,13 @@
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include "libburn.h"
#include "options.h"
#include "drive.h"
@ -39,6 +49,8 @@ struct burn_write_opts *burn_write_opts_new(struct burn_drive *drive)
opts->fill_up_media = 0;
opts->force_is_set = 0;
opts->do_stream_recording = 0;
opts->dvd_obs_override = 0;
opts->stdio_fsync_size = Libburn_stdio_fsync_limiT;
opts->has_mediacatalog = 0;
opts->format = BURN_CDROM;
opts->multi = 0;
@ -143,7 +155,7 @@ int burn_write_opts_set_simulate(struct burn_write_opts *opts, int sim)
int burn_write_opts_set_underrun_proof(struct burn_write_opts *opts,
int underrun_proof)
{
if (!opts->drive->mdata->valid)
if (opts->drive->mdata->valid <= 0)
return 0;
if (opts->drive->mdata->underrun_proof) {
opts->underrun_proof = underrun_proof;
@ -385,10 +397,29 @@ void burn_write_opts_set_force(struct burn_write_opts *opts, int use_force)
void burn_write_opts_set_stream_recording(struct burn_write_opts *opts,
int value)
{
opts->do_stream_recording = !!value;
opts->do_stream_recording = value;
}
/* ts A91115: API */
void burn_write_opts_set_dvd_obs(struct burn_write_opts *opts, int obs)
{
if (obs != 0 && obs != 32 * 1024 && obs != 64 * 1024)
return;
opts->dvd_obs_override = obs;
}
/* ts A91115: API */
void burn_write_opts_set_stdio_fsync(struct burn_write_opts *opts, int rythm)
{
if (rythm == -1)
opts->stdio_fsync_size = 0;
else if (rythm == 0)
opts->stdio_fsync_size = Libburn_stdio_fsync_limiT;
else if (rythm >= 32)
opts->stdio_fsync_size = rythm;
}
/* ts A70901: API */

View File

@ -1,3 +1,9 @@
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifndef BURN__OPTIONS_H
#define BURN__OPTIONS_H
@ -51,9 +57,19 @@ struct burn_write_opts
/* ts A80412 : whether to use WRITE12 with Streaming bit set
rather than WRITE10. Speeds up DVD-RAM. Might help with BD-RE.
This gets transferred to burn_drive.do_stream_recording */
This gets transferred to burn_drive.do_stream_recording
*/
int do_stream_recording;
/* ts A91115 : override value for .obs on DVD media.
Only values 0, 32K and 64K are allowed for now. */
int dvd_obs_override;
/* ts A91115 : size of the fsync() interval for stdio writing.
Values 0 or >= 32 counted in 2 KB blocks. */
int stdio_fsync_size;
/** A disc can have a media catalog number */
int has_mediacatalog;
unsigned char mediacatalog[13];
@ -64,6 +80,11 @@ struct burn_write_opts
unsigned char multi;
};
/* Default value for burn_write_opts.stdio_flush_size
*/
#define Libburn_stdio_fsync_limiT 8192
/** Options for disc reading operations. This should be created with
burn_read_opts_new() and freed with burn_read_opts_free(). */
struct burn_read_opts

63
libburn/os-dummy.h Normal file
View File

@ -0,0 +1,63 @@
/* os-dummy.h
Operating system specific libburn definitions and declarations. Included
by os.h in case of compilation for
Unknown POSIX like systems
with the dummy MMC transport adapter sg-dummy.c
Copyright (C) 2009 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
*/
/** List of all signals which shall be caught by signal handlers and trigger
a graceful abort of libburn. (See man 7 signal.)
*/
/* Once as system defined macros */
#define BURN_OS_SIGNAL_MACRO_LIST \
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, \
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, \
SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN, \
SIGTTOU
/* Once as text 1:1 list of strings for messages and interpreters */
#define BURN_OS_SIGNAL_NAME_LIST \
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT", \
"SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM", \
"SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN", \
"SIGTTOU"
/* The number of above list items */
#define BURN_OS_SIGNAL_COUNT 16
/** To list all signals which shall surely not be caught */
#define BURN_OS_NON_SIGNAL_MACRO_LIST \
SIGKILL, SIGCHLD, SIGSTOP
/* The number of above list items */
#define BURN_OS_NON_SIGNAL_COUNT 3
/* The maximum size for a (SCSI) i/o transaction */
/* Important : MUST be at least 32768 ! */
#define BURN_OS_TRANSPORT_BUFFER_SIZE 65536
/* To hold the position of the most recently delivered address from
device enumeration.
*/
struct burn_drive_enumerator_struct {
int pos;
int info_count;
char **info_list;
};
#define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \
typedef struct burn_drive_enumerator_struct burn_drive_enumerator_t;
/* The list of operating system dependent elements in struct burn_drive.
Usually they are initialized in sg-*.c:enumerate_common().
*/
#define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \
int just_a_dummy;

View File

@ -4,7 +4,7 @@
by os.h in case of compilation for
FreeBSD with CAM
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
*/
/** List of all signals which shall be caught by signal handlers and trigger
@ -57,5 +57,8 @@ typedef struct burn_drive_enumeration_state *burn_drive_enumerator_t;
To be initialized and used within sg-*.c .
*/
#define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \
struct cam_device* cam;
struct cam_device* cam; \
int lock_fd; \
int is_ahci; \

72
libburn/os-libcdio.h Normal file
View File

@ -0,0 +1,72 @@
/* os-libcdio.h
Operating system specific libburn definitions and declarations. Included
by os.h in case of compilation for
Unknown X/Open-like systems
with GNU libcdio MMC transport adapter sg-libcdio.c
Copyright (C) 2009 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
*/
/** List of all signals which shall be caught by signal handlers and trigger
a graceful abort of libburn. (See man 7 signal.)
*/
/* Once as system defined macros */
#define BURN_OS_SIGNAL_MACRO_LIST \
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, \
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, \
SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN, \
SIGTTOU
/* Once as text 1:1 list of strings for messages and interpreters */
#define BURN_OS_SIGNAL_NAME_LIST \
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT", \
"SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM", \
"SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN", \
"SIGTTOU"
/* The number of above list items */
#define BURN_OS_SIGNAL_COUNT 16
/** To list all signals which shall surely not be caught */
#define BURN_OS_NON_SIGNAL_MACRO_LIST \
SIGKILL, SIGCHLD, SIGSTOP
/* The number of above list items */
#define BURN_OS_NON_SIGNAL_COUNT 3
/* The maximum size for a (SCSI) i/o transaction */
/* Important : MUST be at least 32768 ! */
/* My Blu-ray burner LG GGW-H20 writes junk if stream recording is combined
with buffer size 32 kB. So stream recording is allowed only with size 64k.
This makes it worth to have a special case for GNU/Linux buffer size here.
*/
#ifdef __linux
#define BURN_OS_TRANSPORT_BUFFER_SIZE 65536
#else
/* (It might be risky to use 64k. FreeBSD is said to can only 32k.) */
#define BURN_OS_TRANSPORT_BUFFER_SIZE 32768
#endif
/* To hold the position of the most recently delivered address from
device enumeration.
*/
struct burn_drive_enumerator_struct {
char **ppsz_cd_drives;
char **pos;
};
#define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \
typedef struct burn_drive_enumerator_struct burn_drive_enumerator_t;
/* The list of operating system dependent elements in struct burn_drive.
Usually they are initialized in sg-*.c:enumerate_common().
*/
#define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \
void *p_cdio; /* actually a pointer to CdIo_t */ \
char libcdio_name[4096]; /* The drive path as used by libcdio */ \

View File

@ -2,9 +2,10 @@
/* os-linux.h
Operating system specific libburn definitions and declarations. Included
by os.h in case of compilation for
Linux kernels 2.4 and 2.6 with Linux SCSI Generic (sg)
Linux kernels 2.4 and 2.6, GNU/Linux SCSI Generic (sg)
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
Copyright (C) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/

68
libburn/os-solaris.h Normal file
View File

@ -0,0 +1,68 @@
/* os-solaris.h
Operating system specific libburn definitions and declarations. Included
by os.h in case of compilation for
Solaris based systems, e.g. SunOS 5.11
with Solaris uscsi MMC transport adapter sg-solaris.c
Copyright (C) 2010 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
*/
/** List of all signals which shall be caught by signal handlers and trigger
a graceful abort of libburn. (See man signal.h)
*/
/* Once as system defined macros */
#define BURN_OS_SIGNAL_MACRO_LIST \
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, \
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, \
SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN, \
SIGTTOU
/* Once as text 1:1 list of strings for messages and interpreters */
#define BURN_OS_SIGNAL_NAME_LIST \
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT", \
"SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM", \
"SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN", \
"SIGTTOU"
/* The number of above list items */
#define BURN_OS_SIGNAL_COUNT 16
/** To list all signals which shall surely not be caught */
#define BURN_OS_NON_SIGNAL_MACRO_LIST \
SIGKILL, SIGCHLD, SIGSTOP, SIGURG, SIGWINCH
/* The number of above list items */
#define BURN_OS_NON_SIGNAL_COUNT 5
/* The maximum size for a (SCSI) i/o transaction */
/* Important : MUST be at least 32768 ! */
/* My Blu-ray burner LG GGW-H20 writes junk if stream recording is combined
with buffer size 32 kB. So stream recording is allowed only with size 64k.
>>> ??? is 64 kB ok for Solaris uscsi ?
*/
#define BURN_OS_TRANSPORT_BUFFER_SIZE 65536
/* >>> */
/* To hold the position of the most recently delivered address from
device enumeration.
*/
struct burn_drive_enumerator_struct {
void *dir;
};
#define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \
typedef struct burn_drive_enumerator_struct burn_drive_enumerator_t;
/* The list of operating system dependent elements in struct burn_drive.
Usually they are initialized in sg-*.c:enumerate_common().
*/
#define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \
int fd;

View File

@ -3,7 +3,7 @@
Operating system specific libburn definitions and declarations.
The macros defined here are used by libburn modules in order to
avoid own system dependent case distinctions.
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
Copyright (C) 2009 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
*/
#ifndef BURN_OS_H_INCLUDED
@ -13,6 +13,23 @@
Operating system case distinction
*/
#ifdef Libburn_use_sg_dummY
/* --------- Any other system. With dummy MMC transport sg-dummy.c --------- */
#include "os-dummy.h"
#else
#ifdef Libburn_use_libcdiO
/* -------------------------- X/Open with GNU libcdio ---------------------- */
#include "os-libcdio.h"
#else
#ifdef __FreeBSD__
@ -20,14 +37,43 @@
#include "os-freebsd.h"
#else /* operating system case distinction */
#else
#ifdef __FreeBSD_kernel__
/* --------- Linux kernels 2.4 and 2.6 with Linux SCSI Generic (sg) -------- */
/* ----------------------- FreeBSD with CAM under Debian ------------------- */
#include "os-freebsd.h"
#else
#ifdef __linux
/* ------- Linux kernels 2.4 and 2.6 with GNU/Linux SCSI Generic (sg) ------ */
#include "os-linux.h"
#endif /* End of operating system case distinction */
#else
#ifdef __sun
/* ------- Solaris (e.g. SunOS 5.11) with uscsi ------ */
#include "os-solaris.h"
#else
/* --------- Any other system. With dummy MMC transport sg-dummy.c --------- */
#include "os-dummy.h"
#endif /* ! __sun*/
#endif /* ! __linux */
#endif /* ! __FreeBSD__kernel__ */
#endif /* ! __FreeBSD__ */
#endif /* ! Libburn_use_libcdiO */
#endif /* ! Libburn_use_sg_dummY */
#endif /* ! BURN_OS_H_INCLUDED */

View File

@ -1,6 +1,16 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* #include <m alloc.h> ts A61013 : not in Linux man 3 malloc */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
/* #include <m alloc.h> ts A61013 : not in GNU/Linux man 3 malloc */
#include <stdlib.h>
#include <unistd.h>
@ -27,7 +37,6 @@
#include "crc.h"
#include "debug.h"
#include "init.h"
#include "lec.h"
#include "toc.h"
#include "util.h"
#include "sg.h"
@ -95,7 +104,13 @@ drive, or only store a subset of the _opts structs in drives */
fakesub[20] = 2;
fakesub[12] = (d->toc->toc_entry[0].control << 4) +
d->toc->toc_entry[0].adr;
#ifdef Libburn_no_crc_C
crc = 0; /* dummy */
#else
crc = crc_ccitt(fakesub + 12, 10);
#endif
fakesub[22] = crc >> 8;
fakesub[23] = crc & 0xFF;
write(o->subfd, fakesub, 96);
@ -242,6 +257,8 @@ void burn_packet_process(struct burn_drive *d, unsigned char *data,
}
}
crc = (*(sub + 22) << 8) + *(sub + 23);
#ifndef Libburn_no_crc_C
if (crc != crc_ccitt(sub + 12, 10)) {
burn_print(1, "sending error on %s %s\n",
d->idata->vendor, d->idata->product);
@ -250,6 +267,8 @@ void burn_packet_process(struct burn_drive *d, unsigned char *data,
*/
burn_print(1, "crc mismatch in Q\n");
}
#endif
/* else process_q(d, sub + 12); */
/*
if (o->subfd != -1) write(o->subfd, sub, 96); */
@ -323,7 +342,7 @@ int burn_read_data(struct burn_drive *d, off_t byte_address,
int alignment = 2048, start, upto, chunksize = 1, err, cpy_size, i;
int sose_mem = 0, fd = -1, ret;
char msg[81], *wpt;
struct buffer buf;
struct buffer buf, *buffer_mem = d->buffer;
/*
#define Libburn_read_data_adr_logginG 1
@ -371,6 +390,20 @@ int burn_read_data(struct burn_drive *d, off_t byte_address,
msg, 0, 0);
return 0;
}
if (d->media_read_capacity != 0x7fffffff && byte_address >=
((off_t) d->media_read_capacity + (off_t) 1) * (off_t) 2048) {
if (!(flag & 2)) {
sprintf(msg,
"Read start address %ds larger than number of readable blocks %d",
(int) (byte_address / 2048 + !!(byte_address % 2048)),
d->media_read_capacity);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020172,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
}
return 0;
}
if (d->busy != BURN_DRIVE_IDLE) {
libdax_msgs_submit(libdax_messenger,
@ -485,7 +518,7 @@ ex:;
if (fd != -1)
close(fd);
*/
d->buffer = NULL;
d->buffer = buffer_mem;
d->busy = BURN_DRIVE_IDLE;
return ret;
}

View File

@ -2,6 +2,15 @@
/* scsi block commands */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <string.h>
#include <unistd.h>
@ -17,10 +26,31 @@
int mmc_function_spy(struct burn_drive *d, char * text);
/* spc command set */
/* START STOP UNIT as of SBC-1 and SBC-2
0: Opcode 0x1B
1: bit0= Immed
bit1-7= reserved
2: reserved
3: reserved
4: bit0= Start (else Stop unit)
bit1= Load/Eject (according to Start resp. Stop)
bit2-3= reserved
bit4-7= Power Condition
0= Start Valid: process Start and Load/Eject bits
1= assume Active state
2= assume Idle state
3= assume Stanby state
(5= SBC-1 only: assume Sleep state)
7= transfer control of power conditions to logical unit
10= force idle condition timer to 0
11= force standby condition timer to 0
All others are reserved.
5: Control (set to 0)
*/
static unsigned char SBC_LOAD[] = { 0x1b, 0, 0, 0, 3, 0 };
static unsigned char SBC_UNLOAD[] = { 0x1b, 0, 0, 0, 2, 0 };
static unsigned char SBC_START_UNIT[] = { 0x1b, 0, 0, 0, 1, 0 };
static unsigned char SBC_STOP_UNIT[] = { 0x1b, 0, 0, 0, 0, 0 };
void sbc_load(struct burn_drive *d)
{
@ -30,11 +60,6 @@ void sbc_load(struct burn_drive *d)
return;
scsi_init_command(&c, SBC_LOAD, sizeof(SBC_LOAD));
/*
memcpy(c.opcode, SBC_LOAD, sizeof(SBC_LOAD));
c.oplen = sizeof(SBC_LOAD);
c.page = NULL;
*/
c.retry = 1;
/* ts A70921 : Had to revoke Immed because of LG GSA-4082B */
@ -58,50 +83,87 @@ void sbc_eject(struct burn_drive *d)
return;
scsi_init_command(&c, SBC_UNLOAD, sizeof(SBC_UNLOAD));
/*
memcpy(c.opcode, SBC_UNLOAD, sizeof(SBC_UNLOAD));
c.oplen = sizeof(SBC_UNLOAD);
c.page = NULL;
*/
c.opcode[1] |= 1; /* ts A70918 : Immed */
/* c.opcode[1] |= 1; / * ts A70918 : Immed , ts B00109 : revoked */
c.page = NULL;
c.dir = NO_TRANSFER;
d->issue_command(d, &c);
/* ts A70918 : Wait long. A late eject could surprise or hurt user.
ts B00109 : Asynchronous eject revoked, as one cannot reliably
distinguish out from unready.
if (c.error)
return;
/* ts A70918 : Wait long. A late eject could surprise or hurt user. */
spc_wait_unit_attention(d, 1800, "STOP UNIT (+ EJECT)", 0);
*/
}
/* ts A61118 : is it necessary to tell the drive to get ready for use ? */
int sbc_start_unit(struct burn_drive *d)
/* ts A91112 : Now with flag */
/* @param flag bit0= asynchronous waiting
*/
int sbc_start_unit_flag(struct burn_drive *d, int flag)
{
struct command c;
int ret;
if (mmc_function_spy(d, "start_unit") <= 0)
return 0;
scsi_init_command(&c, SBC_START_UNIT, sizeof(SBC_START_UNIT));
/*
memcpy(c.opcode, SBC_START_UNIT, sizeof(SBC_START_UNIT));
c.oplen = sizeof(SBC_START_UNIT);
c.page = NULL;
*/
c.retry = 1;
c.opcode[1] |= 1; /* ts A70918 : Immed */
c.opcode[1] |= (flag & 1); /* ts A70918 : Immed */
c.dir = NO_TRANSFER;
d->issue_command(d, &c);
if (c.error)
return 0;
/* ts A70918 : now asynchronous */
return spc_wait_unit_attention(d, 1800, "START UNIT", 0);
if (!(flag & 1))
return 1;
/* ts A70918 : asynchronous */
ret = spc_wait_unit_attention(d, 1800, "START UNIT", 0);
return ret;
}
int sbc_start_unit(struct burn_drive *d)
{
int ret;
d->is_stopped = 0; /* no endless starting attempts */
/* Asynchronous, not to block controller by waiting */
ret = sbc_start_unit_flag(d, 1);
if (ret <= 0)
return ret;
/* Synchronous to catch Pioneer DVR-216D which is ready too early.
A pending START UNIT can prevent ejecting of the tray.
*/
ret = sbc_start_unit_flag(d, 0);
return ret;
}
/* ts A90824 : Trying to reduce drive noise */
int sbc_stop_unit(struct burn_drive *d)
{
struct command c;
int ret;
if (mmc_function_spy(d, "stop_unit") <= 0)
return 0;
scsi_init_command(&c, SBC_STOP_UNIT, sizeof(SBC_STOP_UNIT));
c.retry = 0;
c.opcode[1] |= 1; /* Immed */
c.dir = NO_TRANSFER;
d->issue_command(d, &c);
if (c.error)
return 0;
ret = spc_wait_unit_attention(d, 1800, "STOP UNIT", 0);
d->is_stopped = 1;
return ret;
}
/* ts A61021 : the sbc specific part of sg.c:enumerate_common()
*/
int sbc_setup_drive(struct burn_drive *d)
@ -109,6 +171,8 @@ int sbc_setup_drive(struct burn_drive *d)
d->eject = sbc_eject;
d->load = sbc_load;
d->start_unit = sbc_start_unit;
d->stop_unit = sbc_stop_unit;
d->is_stopped = 0;
return 1;
}

View File

@ -1,5 +1,11 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifndef __SBC
#define __SBC

View File

@ -1,5 +1,14 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <stdio.h>
/* ts A61010 */
@ -15,13 +24,17 @@
#include "sector.h"
#include "crc.h"
#include "debug.h"
#include "lec.h"
#include "toc.h"
#include "write.h"
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
#include "ecma130ab.h"
#ifdef Libburn_log_in_and_out_streaM
/* <<< ts A61031 */
/* ts A61031 */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
@ -92,7 +105,7 @@ static void get_bytes(struct burn_track *track, int count, unsigned char *data)
int valid, shortage, curr, i, tr;
#ifdef Libburn_log_in_and_out_streaM
/* <<< ts A61031 */
/* ts A61031 */
static int tee_fd= -1;
if(tee_fd==-1)
tee_fd= open("/tmp/libburn_sg_readin",
@ -138,7 +151,7 @@ static void get_bytes(struct burn_track *track, int count, unsigned char *data)
track->sourcecount += valid;
#ifdef Libburn_log_in_and_out_streaM
/* <<< ts A61031 */
/* ts A61031 */
if(tee_fd!=-1 && valid>0) {
write(tee_fd, data + curr, valid);
}
@ -206,8 +219,7 @@ static unsigned char *get_sector(struct burn_write_opts *opts,
{
struct burn_drive *d = opts->drive;
struct buffer *out = d->buffer;
int outmode;
int seclen;
int outmode, seclen;
unsigned char *ret;
outmode = get_outmode(opts);
@ -223,6 +235,7 @@ static unsigned char *get_sector(struct burn_write_opts *opts,
seclen += burn_subcode_length(outmode);
/* ts A61219 : opts->obs is eventually a 32k trigger for DVD */
/* (there is enough buffer size reserve for track->cdxa_conversion) */
if (out->bytes + seclen > BUFFER_SIZE ||
(opts->obs > 0 && out->bytes + seclen > opts->obs)) {
int err;
@ -242,7 +255,6 @@ static unsigned char *get_sector(struct burn_write_opts *opts,
out->bytes = 0;
out->sectors = 0;
}
ret = out->data + out->bytes;
out->bytes += seclen;
out->sectors++;
@ -299,7 +311,17 @@ static int convert_data(struct burn_write_opts *o, struct burn_track *track,
return 0;
if ((outmode & BURN_MODE_BITS) == (inmode & BURN_MODE_BITS)) {
/* see MMC-5 4.2.3.8.5.3 Block Format for Mode 2 form 1 Data
Table 24 Mode 2 Formed Sector Sub-header Format */
if (track != NULL)
if (track->cdxa_conversion == 1)
inlen += 8;
get_bytes(track, inlen, data);
if (track != NULL)
if (track->cdxa_conversion == 1)
memmove(data, data + 8, inlen - 8);
return 1;
}
@ -392,7 +414,13 @@ a2 - lout ctrl
q[7] = dec_to_bcd(d->toc_entry[track].pmin);
q[8] = dec_to_bcd(d->toc_entry[track].psec);
q[9] = dec_to_bcd(d->toc_entry[track].pframe);
#ifdef Libburn_no_crc_C
crc = 0; /* dummy */
#else
crc = crc_ccitt(q, 10);
#endif
q[10] = crc >> 8;
q[11] = crc & 0xFF;
d->toc_temp++;
@ -413,7 +441,8 @@ int sector_toc(struct burn_write_opts *o, int mode)
return 0;
subcode_toc(d, mode, subs);
convert_subs(o, mode, subs, data);
sector_headers(o, data, mode, 1);
if (sector_headers(o, data, mode, 1) <= 0)
return 0;
sector_common(++)
return 1;
}
@ -433,7 +462,8 @@ int sector_pregap(struct burn_write_opts *o,
return 0;
subcode_user(o, subs, tno, control, 0, NULL, 1);
convert_subs(o, mode, subs, data);
sector_headers(o, data, mode, 0);
if (sector_headers(o, data, mode, 0) <= 0)
return 0;
sector_common(--)
return 1;
}
@ -450,11 +480,12 @@ int sector_postgap(struct burn_write_opts *o,
return 0;
/* ts A61010 */
if (convert_data(o, NULL, mode, data) <= 0)
return 0;;
return 0;
/* use last index in track */
subcode_user(o, subs, tno, control, 1, NULL, 1);
convert_subs(o, mode, subs, data);
sector_headers(o, data, mode, 0);
if (sector_headers(o, data, mode, 0) <= 0)
return 0;
sector_common(++)
return 1;
}
@ -486,7 +517,13 @@ static void subcode_lout(struct burn_write_opts *o, unsigned char control,
q[7] = dec_to_bcd(min);
q[8] = dec_to_bcd(sec);
q[9] = dec_to_bcd(frame);
#ifdef Libburn_no_crc_C
crc = 0; /* dummy */
#else
crc = crc_ccitt(q, 10);
#endif
q[10] = crc >> 8;
q[11] = crc & 0xFF;
}
@ -606,7 +643,13 @@ void subcode_user(struct burn_write_opts *o, unsigned char *subcodes,
}
q[0] = (control << 4) + qmode;
#ifdef Libburn_no_crc_C
crc = 0; /* dummy */
#else
crc = crc_ccitt(q, 10);
#endif
q[10] = crc >> 8;
q[11] = crc & 0xff;
}
@ -625,7 +668,8 @@ int sector_lout(struct burn_write_opts *o, unsigned char control, int mode)
return 0;
subcode_lout(o, control, subs);
convert_subs(o, mode, subs, data);
sector_headers(o, data, mode, 0);
if (sector_headers(o, data, mode, 0) <= 0)
return 0;
sector_common(++)
return 1;
}
@ -637,7 +681,7 @@ int sector_data(struct burn_write_opts *o, struct burn_track *t, int psub)
unsigned char *data;
data = get_sector(o, t, t->mode);
if (!data)
if (data == NULL)
return 0;
/* ts A61010 */
if (convert_data(o, t, t->mode, data) <= 0)
@ -660,7 +704,8 @@ int sector_data(struct burn_write_opts *o, struct burn_track *t, int psub)
t->entry->control, 1, &t->isrc, psub);
convert_subs(o, t->mode, subs, data);
sector_headers(o, data, t->mode, 0);
if (sector_headers(o, data, t->mode, 0) <= 0)
return 0;
sector_common(++)
return 1;
}
@ -711,42 +756,27 @@ int sector_headers_is_ok(struct burn_write_opts *o, int mode)
return 0;
}
void sector_headers(struct burn_write_opts *o, unsigned char *out,
/* ts A90830 : changed return type to int
@return 0= failure
1= success
*/
int sector_headers(struct burn_write_opts *o, unsigned char *out,
int mode, int leadin)
{
#ifdef Libburn_ecma130ab_includeD
struct burn_drive *d = o->drive;
unsigned int crc;
int min, sec, frame;
int modebyte = -1;
/* ts A61009 */
#if 1
int ret;
ret = sector_headers_is_ok(o, mode);
if (ret != 2)
return;
return !!ret;
modebyte = 1;
#else
if (mode & BURN_AUDIO) /* no headers for "audio" */
return;
if (o->write_type == BURN_WRITE_SAO)
return;
/* ts A61031 */
if (o->write_type == BURN_WRITE_TAO)
return;
if (mode & BURN_MODE1)
modebyte = 1;
#endif
/* ts A61009 : now ensured by burn_disc_write_is_ok() */
/* a ssert(modebyte == 1); */
out[0] = 0;
memset(out + 1, 0xFF, 10); /* sync */
out[11] = 0;
@ -765,7 +795,13 @@ void sector_headers(struct burn_write_opts *o, unsigned char *out,
out[15] = modebyte;
}
if (mode & BURN_MODE1) {
#ifdef Libburn_no_crc_C
crc = 0; /* dummy */
#else
crc = crc_32(out, 2064);
#endif
out[2064] = crc & 0xFF;
crc >>= 8;
out[2065] = crc & 0xFF;
@ -776,10 +812,33 @@ void sector_headers(struct burn_write_opts *o, unsigned char *out,
}
if (mode & BURN_MODE1) {
memset(out + 2068, 0, 8);
parity_p(out);
parity_q(out);
burn_rspc_parity_p(out);
burn_rspc_parity_q(out);
}
scramble(out);
burn_ecma130_scramble(out);
return 1;
#else /* Libburn_ecma130ab_includeD */
int ret;
ret = sector_headers_is_ok(o, mode);
if (ret != 2)
return (!! ret);
/* ts A90830 : lec.c is copied from cdrdao.
I have no idea yet how lec.c implements the Reed-Solomon encoding
which is described in ECMA-130 for CD-ROM.
So this got removed for now.
*/
libdax_msgs_submit(libdax_messenger, o->drive->global_index,
0x0002010a,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Raw CD write modes are not supported", 0, 0);
return 0;
#endif /* ! Libburn_ecma130ab_includeD */
}
#if 0
@ -835,12 +894,14 @@ void process_q(struct burn_drive *d, unsigned char *q)
*/
int sector_identify(unsigned char *data)
{
scramble(data);
/*
burn_ecma130_scramble(data);
check mode byte for 1 or 2
test parity to see if it's a valid sector
if invalid, return BURN_MODE_AUDIO;
else return mode byte (what about mode 2 formless? heh)
*/
return BURN_MODE1;
}

View File

@ -1,5 +1,10 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifndef __SECTOR
#define __SECTOR
@ -22,7 +27,7 @@ int sector_data(struct burn_write_opts *, struct burn_track *t, int psub);
/* ts A61009 */
int sector_headers_is_ok(struct burn_write_opts *o, int mode);
void sector_headers(struct burn_write_opts *, unsigned char *,
int sector_headers(struct burn_write_opts *, unsigned char *,
int mode, int leadin);
void subcode_user(struct burn_write_opts *, unsigned char *s,
unsigned char tno, unsigned char control,

346
libburn/sg-dummy.c Normal file
View File

@ -0,0 +1,346 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/*
Copyright (c) 2009 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
/*
This is the main operating system dependent SCSI part of libburn. It implements
the transport level aspects of SCSI control and command i/o.
Present implementation: default dummy which enables libburn only to work
with stdio: pseudo drive addresses.
For real implementations see sg-linux.c, sg-freebsd.c,
sg-libcdio.c
*/
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#ifdef Libburn_os_has_statvfS
#include <sys/statvfs.h>
#endif /* Libburn_os_has_stavtfS */
#include "transport.h"
#include "drive.h"
#include "sg.h"
#include "spc.h"
#include "mmc.h"
#include "sbc.h"
#include "debug.h"
#include "toc.h"
#include "util.h"
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
/** Returns the id string of the SCSI transport adapter and eventually
needed operating system facilities.
This call is usable even if sg_initialize() was not called yet. In that
case a preliminary constant message might be issued if detailed info is
not available yet.
@param msg returns id string
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_id_string(char msg[1024], int flag)
{
strcpy(msg, "internal X/Open adapter sg-dummy");
return 1;
}
/** Performs global initialization of the SCSI transport adapter and eventually
needed operating system facilities. Checks for compatibility supporting
software components.
@param msg returns ids and/or error messages of eventual helpers
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_initialize(char msg[1024], int flag)
{
return sg_id_string(msg, 0);
}
/** Performs global finalization of the SCSI transport adapter and eventually
needed operating system facilities. Releases globally aquired resources.
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_shutdown(int flag)
{
return 1;
}
/** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
struct burn_drive which are defined in os-*.h.
This will be called when a burn_drive gets disposed.
@param d the drive to be finalized
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_dispose_drive(struct burn_drive *d, int flag)
{
return 1;
}
/** Returns the next index number and the next enumerated drive address.
The enumeration has to cover all available and accessible drives. It is
allowed to return addresses of drives which are not available but under
some (even exotic) circumstances could be available. It is on the other
hand allowed, only to hand out addresses which can really be used right
in the moment of this call. (This implementation chooses the former.)
@param idx An opaque handle. Make no own theories about it.
@param adr Takes the reply
@param adr_size Gives maximum size of reply including final 0
@param initialize 1 = start new,
0 = continue, use no other values for now
-1 = finish
@return 1 = reply is a valid address , 0 = no further address available
-1 = severe error (e.g. adr_size too small)
*/
int sg_give_next_adr(burn_drive_enumerator_t *idx,
char adr[], int adr_size, int initialize)
{
return 0;
}
/** Brings all available, not-whitelist-banned, and accessible drives into
libburn's list of drives.
*/
/* ts A61115: replacing call to sg-implementation internals from drive.c */
int scsi_enumerate_drives(void)
{
libdax_msgs_submit(libdax_messenger, -1, 0x0002016b,
LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
"No MMC transport adapter is present. Running on sg-dummy.c.",
0, 0);
return 1;
}
/** Tells wether libburn has the given drive in use or exclusively reserved.
If it is "open" then libburn will eventually call sg_release() on it when
it is time to give up usage resp. reservation.
*/
/** Published as burn_drive.drive_is_open() */
int sg_drive_is_open(struct burn_drive * d)
{
return 0;
}
/** Opens the drive for SCSI commands and - if burn activities are prone
to external interference on your system - obtains an exclusive access lock
on the drive. (Note: this is not physical tray locking.)
A drive that has been opened with sg_grab() will eventually be handed
over to sg_release() for closing and unreserving.
*/
int sg_grab(struct burn_drive *d)
{
libdax_msgs_submit(libdax_messenger, d->global_index, 0x0002016a,
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
"No MMC transport adapter is present. Running on sg-dummy.c.",
0, 0);
return 0;
}
/** Gives up the drive for SCSI commands and releases eventual access locks.
(Note: this is not physical tray locking.)
*/
int sg_release(struct burn_drive *d)
{
return 0;
}
/** Sends a SCSI command to the drive, receives reply and evaluates wether
the command succeeded or shall be retried or finally failed.
Returned SCSI errors shall not lead to a return value indicating failure.
The callers get notified by c->error. An SCSI failure which leads not to
a retry shall be notified via scsi_notify_error().
The Libburn_log_sg_commandS facility might be of help when problems with
a drive have to be examined. It shall stay disabled for normal use.
@return: 1 success , <=0 failure
*/
int sg_issue_command(struct burn_drive *d, struct command *c)
{
libdax_msgs_submit(libdax_messenger, d->global_index, 0x0002016a,
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
"No MMC transport adapter is present. Running on sg-dummy.c.",
0, 0);
return -1;
}
/** Tries to obtain SCSI address parameters.
@return 1 is success , 0 is failure
*/
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
int *target_no, int *lun_no)
{
libdax_msgs_submit(libdax_messenger, -1, 0x0002016c,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
"No MMC transport adapter is present. Running on sg-dummy.c.",
0, 0);
return 0;
}
/** Tells wether a text is a persistent address as listed by the enumeration
functions.
*/
int sg_is_enumerable_adr(char *adr)
{
return(0);
}
/* Return 1 if the given path leads to a regular file or a device that can be
seeked, read, and possibly written with 2 kB granularity.
*/
int burn_os_is_2k_seekrw(char *path, int flag)
{
struct stat stbuf;
if (stat(path, &stbuf) == -1)
return 0;
if (S_ISREG(stbuf.st_mode))
return 1;
if (S_ISBLK(stbuf.st_mode))
return 1;
return 0;
}
/** Estimate the potential payload capacity of a file address.
@param path The address of the file to be examined. If it does not
exist yet, then the directory will be inquired.
@param bytes The pointed value gets modified, but only if an estimation is
possible.
@return -2 = cannot perform necessary operations on file object
-1 = neither path nor dirname of path exist
0 = could not estimate size capacity of file object
1 = estimation has been made, bytes was set
*/
int burn_os_stdio_capacity(char *path, off_t *bytes)
{
struct stat stbuf;
#ifdef Libburn_os_has_statvfS
struct statvfs vfsbuf;
#endif
char testpath[4096], *cpt;
long blocks;
off_t add_size = 0;
testpath[0] = 0;
blocks = *bytes / 512;
if (stat(path, &stbuf) == -1) {
strcpy(testpath, path);
cpt = strrchr(testpath, '/');
if(cpt == NULL)
strcpy(testpath, ".");
else if(cpt == testpath)
testpath[1] = 0;
else
*cpt = 0;
if (stat(testpath, &stbuf) == -1)
return -1;
#ifdef Libburn_if_this_was_linuX
} else if(S_ISBLK(stbuf.st_mode)) {
fd = open(path, open_mode);
if (fd == -1)
return -2;
ret = ioctl(fd, BLKGETSIZE, &blocks);
close(fd);
if (ret == -1)
return -2;
*bytes = ((off_t) blocks) * (off_t) 512;
#endif /* Libburn_if_this_was_linuX */
} else if(S_ISREG(stbuf.st_mode)) {
add_size = stbuf.st_blocks * (off_t) 512;
strcpy(testpath, path);
} else
return 0;
if (testpath[0]) {
#ifdef Libburn_os_has_statvfS
if (statvfs(testpath, &vfsbuf) == -1)
return -2;
*bytes = add_size + ((off_t) vfsbuf.f_frsize) *
(off_t) vfsbuf.f_bavail;
#else /* Libburn_os_has_statvfS */
return 0;
#endif /* ! Libburn_os_has_stavtfS */
}
return 1;
}
/* ts A91122 : an interface to open(O_DIRECT) or similar OS tricks. */
#ifdef Libburn_read_o_direcT
/* No special O_DIRECT-like precautions are implemented here */
#endif /* Libburn_read_o_direcT */
int burn_os_open_track_src(char *path, int open_flags, int flag)
{
int fd;
fd = open(path, open_flags);
return fd;
}
void *burn_os_alloc_buffer(size_t amount, int flag)
{
void *buf = NULL;
buf = calloc(1, amount);
return buf;
}
int burn_os_free_buffer(void *buffer, size_t amount, int flag)
{
if (buffer == NULL)
return 0;
free(buffer);
return 1;
}

View File

@ -1,5 +1,11 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/*
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
/*
This is the main operating system dependent SCSI part of libburn. It implements
@ -29,12 +35,28 @@ and of deriving the following system specific files from existing examples:
Said sg-*.c operations are defined by a public function interface, which has
to be implemented in a way that provides libburn with the desired services:
sg_id_string() returns an id string of the SCSI transport adapter.
It may be called before initialization but then may
return only a preliminary id.
sg_initialize() performs global initialization of the SCSI transport
adapter and eventually needed operating system
facilities. Checks for compatibility of supporting
software components.
sg_shutdown() performs global finalizations and releases golbally
aquired resources.
sg_give_next_adr() iterates over the set of potentially useful drive
address strings.
scsi_enumerate_drives() brings all available, not-whitelist-banned, and
accessible drives into libburn's list of drives.
sg_dispose_drive() finalizes adapter specifics of struct burn_drive
on destruction. Releases resources which were aquired
underneath scsi_enumerate_drives().
sg_drive_is_open() tells wether libburn has the given drive in use.
sg_grab() opens the drive for SCSI commands and ensures
@ -48,14 +70,35 @@ sg_issue_command() sends a SCSI command to the drive, receives reply,
sg_obtain_scsi_adr() tries to obtain SCSI address parameters.
burn_os_is_2k_seekrw() tells whether the given path leads to a file object
that can be used in 2 kB granularity by lseek(2),
read(2), and possibly write(2) if not read-only.
E.g. a USB stick or a hard disk.
burn_os_stdio_capacity() estimates the emulated media space of stdio-drives.
burn_os_open_track_src() opens a disk file in a way that allows best
throughput with file reading and/or SCSI write command
transmission.
burn_os_alloc_buffer() allocates a memory area that is suitable for file
descriptors issued by burn_os_open_track_src().
The buffer size may be rounded up for alignment
reasons.
burn_os_free_buffer() delete a buffer obtained by burn_os_alloc_buffer().
Porting hints are marked by the text "PORTING:".
Send feedback to libburn-hackers@pykix.org .
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
/** PORTING : ------- OS dependent headers and definitions ------ */
@ -76,7 +119,7 @@ Send feedback to libburn-hackers@pykix.org .
#include <err.h> /* XXX */
/* ts A70909 : >>> untestet yet wether this compiles */
/* ts A70909 */
#include <sys/statvfs.h>
@ -230,6 +273,61 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
/* ------------------------------------------------------------------------ */
/** Returns the id string of the SCSI transport adapter and eventually
needed operating system facilities.
This call is usable even if sg_initialize() was not called yet. In that
case a preliminary constant message might be issued if detailed info is
not available yet.
@param msg returns id string
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_id_string(char msg[1024], int flag)
{
strcpy(msg, "internal FreeBSD CAM adapter sg-freebsd-port");
return 1;
}
/** Performs global initialization of the SCSI transport adapter and eventually
needed operating system facilities. Checks for compatibility supporting
software components.
@param msg returns ids and/or error messages of eventual helpers
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_initialize(char msg[1024], int flag)
{
return sg_id_string(msg, 0);
}
/** Performs global finalization of the SCSI transport adapter and eventually
needed operating system facilities. Releases globally aquired resources.
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_shutdown(int flag)
{
return 1;
}
/** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
struct burn_drive which are defined in os-*.h.
The eventual initialization of those components was made underneath
scsi_enumerate_drives().
This will be called when a burn_drive gets disposed.
@param d the drive to be finalized
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_dispose_drive(struct burn_drive *d, int flag)
{
return 1;
}
/** Returns the next index number and the next enumerated drive address.
The enumeration has to cover all available and accessible drives. It is
allowed to return addresses of drives which are not available but under
@ -299,7 +397,7 @@ try_item:; /* This spaghetti loop keeps the number of tabs small */
break;
snprintf(buf, sizeof (buf), "/dev/%s%d",
result->periph_name, result->unit_number);
if(adr_size <= strlen(buf)
if(adr_size <= strlen(buf))
return -1;
strcpy(adr, buf);
@ -323,7 +421,7 @@ try_item:; /* This spaghetti loop keeps the number of tabs small */
int scsi_enumerate_drives(void)
{
burn_drive_enumerator_t idx;
int initialize = 1;
int initialize = 1, ret;
char buf[64];
while(1) {
@ -338,6 +436,7 @@ int scsi_enumerate_drives(void)
idx.result->target_lun);
}
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
return 1;
}
@ -360,11 +459,12 @@ int sg_drive_is_open(struct burn_drive * d)
*/
int sg_grab(struct burn_drive *d)
{
int count;
struct cam_device *cam;
if(d->cam != NULL)
return 0;
if(d->cam != NULL) {
d->released = 0;
return 1;
}
cam = cam_open_device(d->devname, O_RDWR);
if (cam == NULL) {
@ -515,7 +615,7 @@ int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
int *target_no, int *lun_no)
{
burn_drive_enumerator_t idx;
int initialize = 1;
int initialize = 1, ret;
char buf[64];
struct periph_match_result* result;
@ -524,7 +624,7 @@ int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
initialize = 0;
if (ret <= 0)
break;
if (strcmp(adr, buf) != 0)
if (strcmp(path, buf) != 0)
continue;
result = &(idx->ccb.cdm.matches[i].result.periph_result);
*bus_no = result->path_id;
@ -546,7 +646,7 @@ int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
int sg_is_enumerable_adr(char* adr)
{
burn_drive_enumerator_t idx;
int initialize = 1;
int initialize = 1, ret;
char buf[64];
while(1) {
@ -564,6 +664,47 @@ int sg_is_enumerable_adr(char* adr)
}
/* ts B00115 */
/* Return 1 if the given path leads to a regular file or a device that can be
seeked, written, and read with 2 kB granularity.
*/
int burn_os_is_2k_seekrw(char *path, int flag)
{
struct stat stbuf;
char *spt;
int i, e;
if (stat(path, &stbuf) == -1)
return 0;
if (S_ISREG(stbuf.st_mode))
return 1;
if (!S_ISCHR(stbuf.st_mode))
return 0;
spt = strrchr(path, '/');
if (spt == NULL)
spt = path;
else
spt++;
e = strlen(spt);
for (i = strlen(spt) - 1; i > 0; i--)
if (spt[i] >= '0' && spt[i] <= '9')
e = i;
if (strncmp(spt, "da", e) == 0) /* SCSI disk. E.g. USB stick. */
return 1;
if (strncmp(spt, "cd", e) == 0) /* SCSI CD drive might be writeable. */
return 1;
if (strncmp(spt, "ad", e) == 0) /* IDE hard drive */
return 1;
if (strncmp(spt, "acd", e) == 0) /* IDE CD drive might be writeable */
return 1;
if (strncmp(spt, "fd", e) == 0) /* Floppy disk */
return 1;
if (strncmp(spt, "fla", e) == 0) /* Flash drive */
return 1;
return 0;
}
/* ts A70909 */
/** Estimate the potential payload capacity of a file address.
@param path The address of the file to be examined. If it does not
@ -623,9 +764,45 @@ int burn_os_stdio_capacity(char *path, off_t *bytes)
if (testpath[0]) {
if (statvfs(testpath, &vfsbuf) == -1)
return -2;
*bytes = add_size + ((off_t) vfsbuf.f_bsize) *
*bytes = add_size + ((off_t) vfsbuf.f_frsize) *
(off_t) vfsbuf.f_bavail;
}
return 1;
}
/* ts A91122 : an interface to open(O_DIRECT) or similar OS tricks. */
#ifdef Libburn_read_o_direcT
/* No special O_DIRECT-like precautions are implemented here */
#endif /* Libburn_read_o_direcT */
int burn_os_open_track_src(char *path, int open_flags, int flag)
{
int fd;
fd = open(path, open_flags);
return fd;
}
void *burn_os_alloc_buffer(size_t amount, int flag)
{
void *buf = NULL;
buf = calloc(1, amount);
return buf;
}
int burn_os_free_buffer(void *buffer, size_t amount, int flag)
{
if (buffer == NULL)
return 0;
free(buffer);
return 1;
}

View File

@ -1,6 +1,14 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
#include <assert.h>
/*
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
@ -8,6 +16,7 @@
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <sys/file.h>
#include <stdlib.h>
#include <string.h>
#include <sys/poll.h>
@ -17,10 +26,24 @@
#include <err.h> /* XXX */
/* ts A70909 : >>> untestet yet wether this compiles */
/* ts A70909 */
#include <sys/statvfs.h>
/* ts B00121 */
#include <sys/disk.h> /* DIOCGMEDIASIZE */
/* ts B00326 : For use of CAM_PASS_ERR_RECOVER with ahci */
#define Libburn_for_freebsd_ahcI yes
/* ts B00327 : for debugging of cam_send_cdb() failures
# define Libburn_ahci_verbouS yes
*/
/* ts B00327 : Apply CAM_PASS_ERR_RECOVER to drives even if not ahci
# define libburn_ahci_style_for_alL yes
*/
#include "transport.h"
#include "drive.h"
@ -55,6 +78,79 @@ int burn_drive_is_banned(char *device_address);
int mmc_function_spy(struct burn_drive *d, char * text);
/* ts B00113
Whether to log SCSI commands:
bit0= log in /tmp/libburn_sg_command_log
bit1= log to stderr
bit2= flush every line
*/
extern int burn_sg_log_scsi;
/* ts B00114 */
/* Storage object is in libburn/init.c
whether to strive for exclusive access to the drive
*/
extern int burn_sg_open_o_excl;
/* ts A91227 */
/** Returns the id string of the SCSI transport adapter and eventually
needed operating system facilities.
This call is usable even if sg_initialize() was not called yet. In that
case a preliminary constant message might be issued if detailed info is
not available yet.
@param msg returns id string
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_id_string(char msg[1024], int flag)
{
strcpy(msg, "internal FreeBSD CAM adapter sg-freebsd");
return 1;
}
/* ts A91227 */
/** Performs global initialization of the SCSI transport adapter and eventually
needed operating system facilities. Checks for compatibility supporting
software components.
@param msg returns ids and/or error messages of eventual helpers
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_initialize(char msg[1024], int flag)
{
return sg_id_string(msg, 0);
}
/* ts A91227 */
/** Performs global finalization of the SCSI transport adapter and eventually
needed operating system facilities. Releases globally aquired resources.
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_shutdown(int flag)
{
return 1;
}
/** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
struct burn_drive which are defined in os-*.h.
The eventual initialization of those components was made underneath
scsi_enumerate_drives().
This will be called when a burn_drive gets disposed.
@param d the drive to be finalized
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_dispose_drive(struct burn_drive *d, int flag)
{
return 1;
}
/* ts A61021 : Moved most code from scsi_enumerate_drives under
sg_give_next_adr() */
/* Some helper functions for scsi_give_next_adr() */
@ -73,6 +169,8 @@ static int sg_init_enumerator(burn_drive_enumerator_t *idx_)
if ((idx->fd = open(XPT_DEVICE, O_RDWR)) == -1) {
warn("couldn't open %s", XPT_DEVICE);
free(idx);
idx = NULL;
return -1;
}
@ -144,7 +242,7 @@ static int sg_next_enumeration_buffer(burn_drive_enumerator_t *idx_)
}
/** Returns the next index number and the next enumerated drive address.
/** Returns the next index object state and the next enumerated drive address.
@param idx An opaque handle. Make no own theories about it.
@param adr Takes the reply
@param adr_size Gives maximum size of reply including final 0
@ -198,9 +296,15 @@ int sg_give_next_adr(burn_drive_enumerator_t *idx_,
struct periph_match_result* result;
result = &(idx->ccb.cdm.matches[idx->i].result.periph_result);
/* ts B00112 : we really want only "cd" devices.
if (idx->skip_device ||
strcmp(result->periph_name, "pass") == 0)
break;
*/
if (idx->skip_device ||
strcmp(result->periph_name, "cd") != 0)
break;
ret = snprintf(adr, adr_size, "/dev/%s%d",
result->periph_name, result->unit_number);
if(ret >= adr_size)
@ -211,7 +315,7 @@ int sg_give_next_adr(burn_drive_enumerator_t *idx_,
}
default:
/* printf(stderr, "unknown match type\n"); */
/* fprintf(stderr, "unknown match type\n"); */
break;
}
(idx->i)++;
@ -286,6 +390,10 @@ int sg_close_drive(struct burn_drive * d)
cam_close_device(d->cam);
d->cam = NULL;
}
if (d->lock_fd > 0) {
close(d->lock_fd);
d->lock_fd = -1;
}
return 0;
}
@ -339,7 +447,10 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
out.lun = lun_no;
out.devname = burn_strdup(fname);
out.cam = NULL;
out.lock_fd = -1;
out.is_ahci = 0;
out.start_lba= -2000000000;
out.end_lba= -2000000000;
@ -431,6 +542,9 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
/* Operating system adapter is CAM */
/* Adapter specific handles and data */
out.cam = NULL;
out.lock_fd = -1;
out.is_ahci = 0;
/* Adapter specific functions */
out.grab = sg_grab;
out.release = sg_release;
@ -443,15 +557,145 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
#endif /* ! Scsi_freebsd_make_own_enumeratE */
/* ts A61021: do not believe this:
we use the sg reference count to decide whether we can use the
drive or not.
if refcount is not one, drive is open somewhere else.
/* Lock the inode associated to dev_fd and the inode associated to devname.
Return OS errno, number of pass device of dev_fd, locked fd to devname,
error message.
A return value of > 0 means success, <= 0 means failure.
*/
static int freebsd_dev_lock(int dev_fd, char *devname,
int *os_errno, int *pass_dev_no, int *lock_fd, char msg[4096],
int flag)
{
int lock_denied = 0, fd_stbuf_valid, name_stbuf_valid, i, pass_l = 100;
int max_retry = 3, tries = 0;
struct stat fd_stbuf, name_stbuf;
char pass_name[16], *lock_name;
*os_errno = 0;
*pass_dev_no = -1;
*lock_fd = -1;
msg[0] = 0;
fd_stbuf_valid = !fstat(dev_fd, &fd_stbuf);
/* Try to find name of pass device by inode number */
lock_name = (char *) "effective device";
if(fd_stbuf_valid) {
for (i = 0; i < pass_l; i++) {
sprintf(pass_name, "/dev/pass%d", i);
if (stat(pass_name, &name_stbuf) != -1)
if(fd_stbuf.st_ino == name_stbuf.st_ino &&
fd_stbuf.st_dev == name_stbuf.st_dev)
break;
}
if (i < pass_l) {
lock_name = pass_name;
*pass_dev_no = i;
}
}
name_stbuf_valid = !stat(devname, &name_stbuf);
for (tries= 0; tries <= max_retry; tries++) {
lock_denied = flock(dev_fd, LOCK_EX | LOCK_NB);
*os_errno = errno;
if (lock_denied) {
if (errno == EAGAIN && tries < max_retry) {
/* <<< debugging
fprintf(stderr,
"\nlibcdio_DEBUG: EAGAIN pass, tries= %d\n",
tries);
*/
usleep(2000000);
continue;
}
sprintf(msg,
"Device busy. flock(LOCK_EX) failed on %s of %s",
strlen(lock_name) > 2000 || *pass_dev_no < 0 ?
"pass device" : lock_name,
strlen(devname) > 2000 ? "drive" : devname);
return 0;
}
break;
}
/*
fprintf(stderr, "libburn_DEBUG: flock obtained on %s of %s\n",
lock_name, devname);
*/
/* Eventually lock the official device node too */
if (fd_stbuf_valid && name_stbuf_valid &&
(fd_stbuf.st_ino != name_stbuf.st_ino ||
fd_stbuf.st_dev != name_stbuf.st_dev)) {
*lock_fd = open(devname, O_RDONLY);
if (*lock_fd == 0) {
close(*lock_fd);
*lock_fd = -1;
} if (*lock_fd > 0) {
for (tries = 0; tries <= max_retry; tries++) {
lock_denied =
flock(*lock_fd, LOCK_EX | LOCK_NB);
if (lock_denied) {
if (errno == EAGAIN &&
tries < max_retry) {
/* <<< debugging
fprintf(stderr,
"\nlibcdio_DEBUG: EAGAIN dev, tries= %d\n",
tries);
*/
usleep(2000000);
continue;
}
close(*lock_fd);
*lock_fd = -1;
sprintf(msg,
"Device busy. flock(LOCK_EX) failed on %s",
strlen(devname) > 4000 ? "drive" : devname);
return 0;
}
break;
}
}
/*
fprintf(stderr, "libburn_DEBUG: flock obtained on %s\n",
devname);
*/
}
return 1;
}
static int sg_lock(struct burn_drive *d, int flag)
{
int ret, os_errno, pass_dev_no = -1, flock_fd = -1;
char msg[4096];
ret = freebsd_dev_lock(d->cam->fd, d->devname,
&os_errno, &pass_dev_no, &flock_fd, msg, 0);
if (ret <= 0) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020008,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, os_errno, 0);
sg_close_drive(d);
return 0;
}
if (d->lock_fd > 0)
close(d->lock_fd);
d->lock_fd = flock_fd;
return 1;
}
int sg_grab(struct burn_drive *d)
{
int count;
struct cam_device *cam;
char path_string[80];
if (mmc_function_spy(d, "sg_grab") <= 0)
return 0;
@ -463,22 +707,31 @@ int sg_grab(struct burn_drive *d)
cam = cam_open_device(d->devname, O_RDWR);
if (cam == NULL) {
libdax_msgs_submit(libdax_messenger, d->global_index, 0x00020003,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Could not grab drive", 0/*os_errno*/, 0);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020003,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Could not grab drive", errno, 0);
return 0;
}
/* er = ioctl(fd, SG_GET_ACCESS_COUNT, &count);*/
count = 1;
if (1 == count) {
d->cam = cam;
fcntl(cam->fd, F_SETOWN, getpid());
d->released = 0;
return 1;
}
burn_print(1, "could not acquire drive - already open\n");
sg_close_drive(d);
return 0;
d->cam = cam;
if (burn_sg_open_o_excl & 63)
if (sg_lock(d, 0) <= 0)
return 0;
fcntl(cam->fd, F_SETOWN, getpid());
cam_path_string(d->cam, path_string, sizeof(path_string));
#ifdef Libburn_ahci_verbouS
fprintf(stderr, "libburn_EXPERIMENTAL: CAM path = %s\n", path_string);
#endif
if (strstr(path_string, ":ahcich") != NULL)
d->is_ahci = 1;
else
d->is_ahci = -1;
d->released = 0;
return 1;
}
@ -506,11 +759,12 @@ int sg_release(struct burn_drive *d)
int sg_issue_command(struct burn_drive *d, struct command *c)
{
int done = 0;
int err;
int done = 0, err, sense_len = 0, ret, ignore_error, no_retry = 0;
int cam_pass_err_recover = 0;
union ccb *ccb;
char buf[161];
static FILE *fp = NULL;
snprintf(buf, sizeof (buf), "sg_issue_command d->cam=%p d->released=%d",
(void*)d->cam, d->released);
mmc_function_spy(NULL, buf);
@ -519,6 +773,15 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
c->error = 0;
return 0;
}
if (burn_sg_log_scsi & 1) {
if (fp == NULL) {
fp= fopen("/tmp/libburn_sg_command_log", "a");
fprintf(fp,
"\n-----------------------------------------\n");
}
}
if (burn_sg_log_scsi & 3)
scsi_log_cmd(c,fp,0);
c->error = 0;
@ -545,6 +808,23 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
break;
}
#ifdef Libburn_for_freebsd_ahcI
/* ts B00325 : Advise by Alexander Motin */
/* Runs well on 8-STABLE (23 Mar 2003)
But on 8-RELEASE cam_send_ccb() returns non-zero with errno 6
on eject. Long lasting TEST UNIT READY cycles break with
errno 16.
*/
#ifdef Libburn_ahci_style_for_alL
{
#else
if (d->is_ahci > 0) {
#endif
ccb->ccb_h.flags |= CAM_PASS_ERR_RECOVER;
cam_pass_err_recover = 1;
}
#endif /* Libburn_for_freebsd_ahcI */
ccb->csio.cdb_len = c->oplen;
memcpy(&ccb->csio.cdb_io.cdb_bytes, &c->opcode, c->oplen);
@ -553,11 +833,20 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
if (c->page) {
ccb->csio.data_ptr = c->page->data;
if (c->dir == FROM_DRIVE) {
ccb->csio.dxfer_len = BUFFER_SIZE;
/* ts A90430 : Ticket 148 , by jwehle :
"On ... FreeBSD 6.4 which has a usb memory reader in
addition to a ATAPI DVD burner sg_issue_command
will hang while the SCSI bus is being scanned"
*/
if (c->dxfer_len >= 0)
ccb->csio.dxfer_len = c->dxfer_len;
else
ccb->csio.dxfer_len = BUFFER_SIZE;
/* touch page so we can use valgrind */
memset(c->page->data, 0, BUFFER_SIZE);
} else {
assert(c->page->bytes > 0);
ccb->csio.dxfer_len = c->page->bytes;
}
} else {
@ -566,31 +855,114 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
}
do {
memset(c->sense, 0, sizeof(c->sense));
err = cam_send_ccb(d->cam, ccb);
if (err == -1) {
ignore_error = sense_len = 0;
/* ts B00325 : CAM_AUTOSNS_VALID advised by Alexander Motin */
if (ccb->ccb_h.status & CAM_AUTOSNS_VALID) {
/* ts B00110 */
/* Better curb sense_len */
sense_len = ccb->csio.sense_len;
if (sense_len > sizeof(c->sense))
sense_len = sizeof(c->sense);
memcpy(c->sense, &ccb->csio.sense_data, sense_len);
if (sense_len >= 14 && cam_pass_err_recover &&
(c->sense[2] & 0x0f))
ignore_error = 1;
}
if (err == -1 && cam_pass_err_recover && ! ignore_error) {
#ifdef Libburn_ahci_verbouS
fprintf(stderr, "libburn_EXPERIMENTAL: errno = %d . cam_errbuf = '%s'\n", errno, cam_errbuf);
#endif
if (errno == ENXIO && c->opcode[0] != 0) {
/* Operations on empty or ejected tray */
/* MEDIUM NOT PRESENT */
#ifdef Libburn_ahci_verbouS
fprintf(stderr, "libburn_EXPERIMENTAL: Emulating [2,3A,00] MEDIUM NOT PRESENT\n");
#endif
c->sense[2] = 0x02;
c->sense[12] = 0x3A;
c->sense[13] = 0x00;
sense_len = 14;
ignore_error = 1;
} else if (c->opcode[0] == 0 &&
(errno == EBUSY || errno == ENXIO)) {
/* Timeout of TEST UNIT READY loop */
/* Inquiries while tray is being loaded */
/*LOGICAL UNIT NOT READY,CAUSE NOT REPORTABLE*/
#ifdef Libburn_ahci_verbouS
fprintf(stderr, "libburn_EXPERIMENTAL: Emulating [2,04,00] LOGICAL UNIT NOT READY,CAUSE NOT REPORTABLE\n");
#endif
c->sense[2] = 0x02;
c->sense[12] = 0x04;
c->sense[13] = 0x00;
sense_len = 14;
ignore_error = 1;
} else if (errno == EINVAL) {
/* Inappropriate MODE SENSE */
/* INVALID FIELD IN CDB */
#ifdef Libburn_ahci_verbouS
fprintf(stderr, "libburn_EXPERIMENTAL: Emulating [5,24,00] INVALID FIELD IN CDB\n");
#endif
c->sense[2] = 0x05;
c->sense[12] = 0x24;
c->sense[13] = 0x00;
sense_len = 14;
ignore_error = 1;
}
}
if (err == -1 && !ignore_error) {
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x0002010c,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Failed to transfer command to drive",
errno, 0);
cam_freeccb(ccb);
sg_close_drive(d);
d->released = 1;
d->busy = BURN_DRIVE_IDLE;
c->error = 1;
return -1;
{ret = -1; goto ex;}
}
/* XXX */
memcpy(c->sense, &ccb->csio.sense_data, ccb->csio.sense_len);
if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
if (!c->retry) {
if (sense_len < 14) {
/*LOGICAL UNIT NOT READY,CAUSE NOT REPORTABLE*/
#ifdef Libburn_ahci_verbouS
fprintf(stderr, "libburn_EXPERIMENTAL: CAM_STATUS= %d .Emulating [2,04,00] LOGICAL UNIT NOT READY,CAUSE NOT REPORTABLE\n", (ccb->ccb_h.status & CAM_STATUS_MASK));
#endif
c->sense[2] = 0x02;
c->sense[12] = 0x04;
c->sense[13] = 0x00;
no_retry = 1;
}
if (no_retry || ignore_error || !c->retry) {
c->error = 1;
cam_freeccb(ccb);
return 1;
{ret = 1; goto ex;}
}
switch (scsi_error(d, c->sense, 0)) {
case RETRY:
done = 0;
if (burn_sg_log_scsi & 3) {
/* >>> Need own duration time
measurement. Then remove bit1 */
scsi_log_err(c, fp, c->sense, 0,
(c->error != 0) | 2);
scsi_log_cmd(c,fp,0);
}
break;
case FAIL:
done = 1;
@ -601,8 +973,58 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
done = 1;
}
} while (!done);
ret = 1;
ex:;
if (c->error)
scsi_notify_error(d, c, c->sense, 18, 0);
if (burn_sg_log_scsi & 3)
/* >>> Need own duration time measurement. Then remove bit1 */
scsi_log_err(c, fp, c->sense, 0, (c->error != 0) | 2);
cam_freeccb(ccb);
return 1;
return ret;
}
/* ts B00115 */
/* Return 1 if the given path leads to a regular file or a device that can be
seeked, read and eventually written with 2 kB granularity.
*/
int burn_os_is_2k_seekrw(char *path, int flag)
{
struct stat stbuf;
char *spt;
int i, e;
if (stat(path, &stbuf) == -1)
return 0;
if (S_ISREG(stbuf.st_mode))
return 1;
if (!S_ISCHR(stbuf.st_mode))
return 0;
spt = strrchr(path, '/');
if (spt == NULL)
spt = path;
else
spt++;
e = strlen(spt);
for (i = strlen(spt) - 1; i > 0; i--)
if (spt[i] >= '0' && spt[i] <= '9')
e = i;
if (strncmp(spt, "da", e) == 0) /* SCSI disk. E.g. USB stick. */
return 1;
if (strncmp(spt, "cd", e) == 0) /* SCSI CD drive might be writeable. */
return 1;
if (strncmp(spt, "ad", e) == 0) /* IDE hard drive */
return 1;
if (strncmp(spt, "acd", e) == 0) /* IDE CD drive might be writeable */
return 1;
if (strncmp(spt, "fd", e) == 0) /* Floppy disk */
return 1;
if (strncmp(spt, "fla", e) == 0) /* Flash drive */
return 1;
return 0;
}
@ -622,8 +1044,8 @@ int burn_os_stdio_capacity(char *path, off_t *bytes)
struct statvfs vfsbuf;
char testpath[4096], *cpt;
long blocks;
int open_mode = O_RDWR, fd, ret;
off_t add_size = 0;
int fd, ret;
testpath[0] = 0;
blocks = *bytes / 512;
@ -642,6 +1064,8 @@ int burn_os_stdio_capacity(char *path, off_t *bytes)
#ifdef Libburn_if_this_was_linuX
} else if(S_ISBLK(stbuf.st_mode)) {
int open_mode = O_RDWR, fd, ret;
if(burn_sg_open_o_excl)
open_mode |= O_EXCL;
fd = open(path, open_mode);
@ -656,6 +1080,15 @@ int burn_os_stdio_capacity(char *path, off_t *bytes)
#endif /* Libburn_if_this_was_linuX */
} else if(S_ISCHR(stbuf.st_mode)) {
fd = open(path, O_RDONLY);
if (fd == -1)
return -2;
ret = ioctl(fd, DIOCGMEDIASIZE, &add_size);
close(fd);
if (ret == -1)
return -2;
*bytes = add_size;
} else if(S_ISREG(stbuf.st_mode)) {
add_size = stbuf.st_blocks * (off_t) 512;
strcpy(testpath, path);
@ -665,9 +1098,45 @@ int burn_os_stdio_capacity(char *path, off_t *bytes)
if (testpath[0]) {
if (statvfs(testpath, &vfsbuf) == -1)
return -2;
*bytes = add_size + ((off_t) vfsbuf.f_bsize) *
*bytes = add_size + ((off_t) vfsbuf.f_frsize) *
(off_t) vfsbuf.f_bavail;
}
return 1;
}
/* ts A91122 : an interface to open(O_DIRECT) or similar OS tricks. */
#ifdef Libburn_read_o_direcT
/* No special O_DIRECT-like precautions are implemented here */
#endif /* Libburn_read_o_direcT */
int burn_os_open_track_src(char *path, int open_flags, int flag)
{
int fd;
fd = open(path, open_flags);
return fd;
}
void *burn_os_alloc_buffer(size_t amount, int flag)
{
void *buf = NULL;
buf = calloc(1, amount);
return buf;
}
int burn_os_free_buffer(void *buffer, size_t amount, int flag)
{
if (buffer == NULL)
return 0;
free(buffer);
return 1;
}

1000
libburn/sg-libcdio.c Normal file

File diff suppressed because it is too large Load Diff

View File

@ -1,11 +1,23 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
/* <<< ts A91112 : experiments to get better speed with USB
#define Libburn_sgio_as_growisofS 1
*/
/*
This is the main operating system dependent SCSI part of libburn. It implements
the transport level aspects of SCSI control and command i/o.
Present implementation: Linux SCSI Generic (sg)
Present implementation: GNU/Linux SCSI Generic (sg)
PORTING:
@ -29,12 +41,28 @@ and of deriving the following system specific files from existing examples:
Said sg-*.c operations are defined by a public function interface, which has
to be implemented in a way that provides libburn with the desired services:
sg_id_string() returns an id string of the SCSI transport adapter.
It may be called before initialization but then may
return only a preliminary id.
sg_initialize() performs global initialization of the SCSI transport
adapter and eventually needed operating system
facilities. Checks for compatibility of supporting
software components.
sg_shutdown() performs global finalizations and releases golbally
aquired resources.
sg_give_next_adr() iterates over the set of potentially useful drive
address strings.
scsi_enumerate_drives() brings all available, not-whitelist-banned, and
accessible drives into libburn's list of drives.
sg_dispose_drive() finalizes adapter specifics of struct burn_drive
on destruction. Releases resources which were aquired
underneath scsi_enumerate_drives().
sg_drive_is_open() tells wether libburn has the given drive in use.
sg_grab() opens the drive for SCSI commands and ensures
@ -48,8 +76,25 @@ sg_issue_command() sends a SCSI command to the drive, receives reply,
sg_obtain_scsi_adr() tries to obtain SCSI address parameters.
burn_os_is_2k_seekrw() tells whether the given path leads to a file object
that can be used in 2 kB granularity by lseek(2) and
read(2), and possibly write(2) if not read-only.
E.g. a USB stick or a hard disk.
burn_os_stdio_capacity() estimates the emulated media space of stdio-drives.
burn_os_open_track_src() opens a disk file in a way that allows best
throughput with file reading and/or SCSI write command
transmission.
burn_os_alloc_buffer() allocates a memory area that is suitable for file
descriptors issued by burn_os_open_track_src().
The buffer size may be rounded up for alignment
reasons.
burn_os_free_buffer() delete a buffer obtained by burn_os_alloc_buffer().
Porting hints are marked by the text "PORTING:".
Send feedback to libburn-hackers@pykix.org .
@ -59,9 +104,20 @@ Hint: You should also look into sg-freebsd-port.c, which is a younger and
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
/** PORTING : ------- OS dependent headers and definitions ------ */
#ifdef Libburn_read_o_direcT
# ifndef _GNU_SOURCE
# define _GNU_SOURCE
# endif
#endif /* Libburn_read_o_direcT */
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
@ -80,6 +136,9 @@ Hint: You should also look into sg-freebsd-port.c, which is a younger and
/* for ioctl(BLKGETSIZE) */
#include <linux/fs.h>
/* for mmap() */
#include <sys/mman.h>
#include <scsi/sg.h>
/* Values within sg_io_hdr_t indicating success after ioctl(SG_IO) : */
@ -158,9 +217,17 @@ static char linux_ata_device_family[80] = {"/dev/hd%c"};
static int linux_ata_enumerate_verbous = 0;
/* The waiting time before eventually retrying a failed SCSI command.
Before each retry wait Libburn_sg_linux_retry_incR longer than with
the previous one.
*/
#define Libburn_sg_linux_retry_usleeP 100000
#define Libburn_sg_linux_retry_incR 100000
/** PORTING : ------ libburn portable headers and definitions ----- */
#include "libburn.h"
#include "transport.h"
#include "drive.h"
#include "sg.h"
@ -189,17 +256,25 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
/* ts A60813 : storage objects are in libburn/init.c
wether to use O_EXCL with open(2) of devices
wether to use fcntl(,F_SETLK,) after open(2) of devices
whether to use O_EXCL with open(2) of devices
whether 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 take O_EXCL rejection as fatal error */
whether to use O_NOBLOCK with open(2) on devices
whether to take O_EXCL rejection as fatal error
*/
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_abort_busy;
/* ts A91111 :
whether to log SCSI commands:
bit0= log in /tmp/libburn_sg_command_log
bit1= log to stderr
bit2= flush every line
*/
extern int burn_sg_log_scsi;
/* ts A60821
debug: for tracing calls which might use open drive fds
@ -470,7 +545,7 @@ static int sg_fcntl_lock(int *fd, char *fd_name, int l_type, int verbous)
/* ts A60926 */
static int sg_open_drive_fd(char *fname, int scan_mode)
{
int open_mode = O_RDWR, fd;
int open_mode = O_RDWR, fd, tries= 0;
char msg[81];
/* ts A70409 : DDLP-B */
@ -502,7 +577,8 @@ static int sg_open_drive_fd(char *fname, int scan_mode)
"libburn: experimental: O_EXCL= %d , O_NDELAY= %d\n",
!!(open_mode&O_EXCL),!!(open_mode&O_NDELAY));
*/
try_open:;
fd = open(fname, open_mode);
if (fd == -1) {
/* <<< debugging
@ -511,6 +587,17 @@ static int sg_open_drive_fd(char *fname, int scan_mode)
fname,errno);
*/
if (errno == EBUSY) {
tries++;
/* <<< debugging
fprintf(stderr,
"\nlibburn_DEBUG: EBUSY , tries= %d\n", tries);
*/
if (tries < 4) {
usleep(2000000);
goto try_open;
}
sg_handle_busy_device(fname, errno);
return -1;
@ -729,19 +816,17 @@ static int is_scsi_drive(char *fname, int *bus_no, int *host_no,
}
#ifdef CDROM_DRIVE_STATUS
if (strcmp(linux_sg_device_family,"/dev/sg%d") != 0) {
/* http://developer.osdl.org/dev/robustmutexes/
/* http://developer.osdl.org/dev/robustmutexes/
src/fusyn.hg/Documentation/ioctl/cdrom.txt */
sid_ret = ioctl(fd, CDROM_DRIVE_STATUS, 0);
if(linux_sg_enumerate_debug)
fprintf(stderr,
"ioctl(CDROM_DRIVE_STATUS) = %d , ",
sid_ret);
if (sid_ret != -1 && sid_ret != CDS_NO_INFO)
sid.scsi_type = TYPE_ROM;
else
sid_ret = -1;
}
sid_ret = ioctl(fd, CDROM_DRIVE_STATUS, 0);
if(linux_sg_enumerate_debug)
fprintf(stderr,
"ioctl(CDROM_DRIVE_STATUS) = %d , ",
sid_ret);
if (sid_ret != -1 && sid_ret != CDS_NO_INFO)
sid.scsi_type = TYPE_ROM;
else
sid_ret = -1;
#endif /* CDROM_DRIVE_STATUS */
}
@ -795,7 +880,7 @@ static int is_scsi_drive(char *fname, int *bus_no, int *host_no,
if (ret<=0) {
if (linux_sg_enumerate_debug)
fprintf(stderr, "cannot lock siblings\n");
sg_handle_busy_device(fname, 0);
sg_handle_busy_device(fname, 0);
return 0;
}
/* the final occupation will be done in sg_grab() */
@ -818,7 +903,7 @@ static int is_scsi_drive(char *fname, int *bus_no, int *host_no,
#endif /* Libburn_drive_new_deaL */
/** Speciality of Linux: detect non-SCSI ATAPI (EIDE) which will from
/** Speciality of GNU/Linux: detect non-SCSI ATAPI (EIDE) which will from
then on used used via generic SCSI as is done with (emulated) SCSI drives */
static void ata_enumerate(void)
{
@ -1130,7 +1215,8 @@ static int fname_drive_is_listed(char *fname, int flag)
/* ts A80731 : Directly open the given address.
@param flag bit0= do not compain about missing file
@param flag bit0= do not complain about missing file
bit1= do not check whether drive is already listed
*/
static int fname_enumerate(char *fname, int flag)
{
@ -1139,8 +1225,9 @@ static int fname_enumerate(char *fname, int flag)
char msg[BURN_DRIVE_ADR_LEN + 80];
struct stat stbuf;
if (fname_drive_is_listed(fname, 0))
return 2;
if (!(flag & 2))
if (fname_drive_is_listed(fname, 0))
return 2;
if (stat(fname, &stbuf) == -1) {
sprintf(msg, "File object '%s' not found", fname);
if (!(flag & 1))
@ -1183,7 +1270,7 @@ static int single_enumerate(int flag)
fname= burn_drive_whitelist_item(0, 0);
if (fname == NULL)
return 0;
ret = fname_enumerate(fname, 0);
ret = fname_enumerate(fname, 2);
if (ret <= 0) {
sprintf(msg, "Cannot access '%s' as SG_IO CDROM drive", fname);
libdax_msgs_submit(libdax_messenger, -1, 0x0002000a,
@ -1216,6 +1303,9 @@ static int proc_sys_dev_cdrom_info(char ***list, int *count, int flag)
return 1;
*count = 0;
sg_evaluate_kernel();
if (sg_kernel_age < 2) /* addresses are not suitable for kernel 2.4 */
return 1;
fp = fopen("/proc/sys/dev/cdrom/info", "r");
if (fp == NULL)
return 0;
@ -1322,7 +1412,7 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
/* PORTING: ------------------- non portable part --------------- */
/* Operating system adapter is Linux Generic SCSI (sg) */
/* Operating system adapter is GNU/Linux Generic SCSI (sg) */
/* Adapter specific handles and data */
out.fd = -1337;
out.sibling_count = 0;
@ -1348,8 +1438,63 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
/* ------------------------------------------------------------------------ */
/** Returns the id string of the SCSI transport adapter and eventually
needed operating system facilities.
This call is usable even if sg_initialize() was not called yet. In that
case a preliminary constant message might be issued if detailed info is
not available yet.
@param msg returns id string
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_id_string(char msg[1024], int flag)
{
strcpy(msg, "internal GNU/Linux SG_IO adapter sg-linux");
return 1;
}
/** Performs global initialization of the SCSI transport adapter and eventually
needed operating system facilities. Checks for compatibility supporting
software components.
@param msg returns ids and/or error messages of eventual helpers
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_initialize(char msg[1024], int flag)
{
return sg_id_string(msg, 0);
}
/** Performs global finalization of the SCSI transport adapter and eventually
needed operating system facilities. Releases globally aquired resources.
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_shutdown(int flag)
{
return 1;
}
/** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
struct burn_drive which are defined in os-*.h.
The eventual initialization of those components was made underneath
scsi_enumerate_drives().
This will be called when a burn_drive gets disposed.
@param d the drive to be finalized
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_dispose_drive(struct burn_drive *d, int flag)
{
return 1;
}
/** PORTING:
In this Linux implementation, this function mirrors the enumeration
In this GNU/Linux implementation, this function mirrors the enumeration
done in sg_enumerate and ata_enumerate(). It would be better to base those
functions on this sg_give_next_adr() but the situation is not inviting.
*/
@ -1446,7 +1591,7 @@ return_1_pre_proc:;
libburn's list of drives.
*/
/** PORTING:
If not stricken with an incompletely unified situation like in Linux
If not stricken with an incompletely unified situation like in GNU/Linux
one would rather implement this by a loop calling sg_give_next_adr().
If needed with your sg_give_next_adr() results, do a test for existence
and accessability. If burn activities are prone to external interference
@ -1510,6 +1655,7 @@ int sg_drive_is_open(struct burn_drive * d)
int sg_grab(struct burn_drive *d)
{
int fd, os_errno= 0, ret;
int max_tries = 3, tries = 0;
/* ts A60813 */
int open_mode = O_RDWR;
@ -1543,6 +1689,7 @@ int sg_grab(struct burn_drive *d)
value -1 of open(2) war used. */
if(! burn_drive_is_open(d)) {
try_open:;
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy(NULL, "sg_grab ----------- opening");
@ -1576,13 +1723,19 @@ int sg_grab(struct burn_drive *d)
fcntl(fd, F_SETOWN, getpid());
d->released = 0;
return 1;
}
} else if (errno == EBUSY)
goto drive_is_in_use;
libdax_msgs_submit(libdax_messenger, d->global_index, 0x00020003,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Could not grab drive", os_errno, 0);
return 0;
drive_is_in_use:;
tries++;
if (tries < max_tries) {
usleep(2000000);
goto try_open;
}
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020003,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
@ -1620,69 +1773,34 @@ 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;
}
#ifdef NIX
/* <<< now in spc.c as scsi_log_err */
/** 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)
if(fp != NULL && (fp == stderr || (burn_sg_log_scsi & 1))) {
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
} else {
scsi_show_cmd_reply(c, fp, 0);
fprintf(fp,"%6d ms\n", s->duration);
#ifdef Libburn_fflush_log_sg_commandS
fflush(fp);
#endif
}
if (burn_sg_log_scsi & 4)
fflush(fp);
}
if (fp == stderr)
if (fp == stderr || !(burn_sg_log_scsi & 2))
return 1;
#ifdef Libburn_log_sg_command_stderR
sg_log_err(c, stderr, s, flag);
#endif
return 1;
}
#endif /* Libburn_log_sg_commandS */
#endif /* NIX */
/** Sends a SCSI command to the drive, receives reply and evaluates wether
@ -1690,20 +1808,16 @@ static int sg_log_err(struct command *c, FILE *fp,
Returned SCSI errors shall not lead to a return value indicating failure.
The callers get notified by c->error. An SCSI failure which leads not to
a retry shall be notified via scsi_notify_error().
The Libburn_log_sg_commandS facility might be of help when problems with
a drive have to be examined. It shall stay disabled for normal use.
@return: 1 success , <=0 failure
*/
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, usleep_time, i;
int err;
time_t start_time;
sg_io_hdr_t s;
#ifdef Libburn_log_sg_commandS
/* ts A61030 */
static FILE *fp= NULL;
#endif /* Libburn_log_sg_commandS */
/* <<< ts A60821
debug: for tracing calls which might use open drive fds */
@ -1712,15 +1826,16 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
d->fd,d->released);
mmc_function_spy(NULL, buf);
#ifdef Libburn_log_sg_commandS
/* ts A61030 */
if(fp==NULL) {
fp= fopen("/tmp/libburn_sg_command_log","a");
fprintf(fp,"\n-----------------------------------------\n");
if (burn_sg_log_scsi & 1) {
if (fp == NULL) {
fp= fopen("/tmp/libburn_sg_command_log", "a");
fprintf(fp,
"\n-----------------------------------------\n");
}
}
sg_log_cmd(c,fp,0);
#endif /* Libburn_log_sg_commandS */
if (burn_sg_log_scsi & 3)
scsi_log_cmd(c,fp,0);
/* ts A61010 : with no fd there is no chance to send an ioctl */
if (d->fd < 0) {
@ -1733,6 +1848,13 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
s.interface_id = 'S';
#ifdef Libburn_sgio_as_growisofS
/* ??? ts A91112 : does this speed up USB ? (from growisofs)
--- did not help
*/
s.flags = SG_FLAG_DIRECT_IO;
#endif /* Libburn_sgio_as_growisofS */
if (c->dir == TO_DRIVE)
s.dxfer_direction = SG_DXFER_TO_DEV;
else if (c->dir == FROM_DRIVE)
@ -1781,7 +1903,8 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
}
s.usr_ptr = c;
do {
start_time = time(NULL);
for(i = 0; !done; i++) {
err = ioctl(d->fd, SG_IO, &s);
/* ts A61010 */
@ -1809,16 +1932,33 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
switch (scsi_error(d, s.sbp, s.sb_len_wr)) {
case RETRY:
done = 0;
if (burn_sg_log_scsi & 3) {
scsi_log_err(c, fp, s.sbp, s.duration,
c->error != 0);
scsi_log_cmd(c,fp,0);
}
break;
case FAIL:
done = 1;
c->error = 1;
break;
}
/* ts A90921 :
Calming down retries and breaking up endless cycle
*/
usleep_time = Libburn_sg_linux_retry_usleeP +
i * Libburn_sg_linux_retry_incR;
if (time(NULL) + usleep_time / 1000000 - start_time >
s.timeout / 1000 + 1) {
c->error = 1;
goto ex;
}
usleep(usleep_time);
} else {
done = 1;
}
} while (!done);
}
/* ts A61106 */
ex:;
@ -1840,11 +1980,9 @@ ex:;
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
}
#ifdef Libburn_log_sg_commandS
sg_log_err(c, fp, &s, c->error != 0);
#endif /* Libburn_log_sg_commandS */
if (burn_sg_log_scsi & 3)
/* <<< sg_log_err(c, fp, &s, c->error != 0); */
scsi_log_err(c, fp, s.sbp, s.duration, c->error != 0);
return 1;
}
@ -1863,6 +2001,8 @@ int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
};
struct my_scsi_idlun idlun;
/* valgrind called idlun unitialized because it is blind for ioctl */
memset(&idlun, 0, sizeof(struct my_scsi_idlun));
l = strlen(linux_ata_device_family) - 2;
if (l > 0 && strncmp(path, linux_ata_device_family, l) == 0
@ -1938,6 +2078,24 @@ int sg_is_enumerable_adr(char *adr)
}
/* ts B00115 */
/* Return 1 if the given path leads to a regular file or a device that can be
seeked, read, and possibly written with 2 kB granularity.
*/
int burn_os_is_2k_seekrw(char *path, int flag)
{
struct stat stbuf;
if (stat(path, &stbuf) == -1)
return 0;
if (S_ISREG(stbuf.st_mode))
return 1;
if (S_ISBLK(stbuf.st_mode))
return 1;
return 0;
}
/* ts A70909 */
/** Estimate the potential payload capacity of a file address.
@param path The address of the file to be examined. If it does not
@ -1989,9 +2147,86 @@ int burn_os_stdio_capacity(char *path, off_t *bytes)
if (testpath[0]) {
if (statvfs(testpath, &vfsbuf) == -1)
return -2;
*bytes = add_size + ((off_t) vfsbuf.f_bsize) *
*bytes = add_size + ((off_t) vfsbuf.f_frsize) *
(off_t) vfsbuf.f_bavail;
}
return 1;
}
/* ts A91122 : an interface to open(O_DIRECT) or similar OS tricks. */
#ifdef PROT_READ
#ifdef PROT_WRITE
#ifdef MAP_SHARED
#ifdef MAP_ANONYMOUS
#ifdef MAP_FAILED
#define Libburn_linux_do_mmaP 1
#endif
#endif
#endif
#endif
#endif
#ifdef Libburn_read_o_direcT
#ifdef O_DIRECT
#define Libburn_linux_do_o_direcT 1
#endif
#endif /* Libburn_read_o_direcT */
int burn_os_open_track_src(char *path, int open_flags, int flag)
{
int fd;
#ifdef Libburn_linux_do_o_direcT
libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
"Opening track source with O_DIRECT" , 0, 0);
fd = open(path, open_flags | O_DIRECT);
#else
fd = open(path, open_flags);
#endif
return fd;
}
void *burn_os_alloc_buffer(size_t amount, int flag)
{
void *buf = NULL;
#ifdef Libburn_linux_do_mmaP
/* >>> check whether size is suitable */;
libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
"Allocating buffer via mmap()" , 0, 0);
buf = mmap(NULL, amount, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, (off_t) 0);
if (buf == MAP_FAILED)
buf = NULL;
else
memset(buf, 0, amount);
#else
buf = calloc(1, amount);
#endif /* ! Libburn_linux_do_mmaP */
return buf;
}
int burn_os_free_buffer(void *buffer, size_t amount, int flag)
{
int ret = 0;
if (buffer == NULL)
return 0;
#ifdef Libburn_linux_do_mmaP
ret = munmap(buffer, amount);
#else
free(buffer);
#endif
return (ret == 0);
}

868
libburn/sg-solaris.c Normal file
View File

@ -0,0 +1,868 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/*
Copyright (c) 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
/*
This is the main operating system dependent SCSI part of libburn. It implements
the transport level aspects of SCSI control and command i/o.
Present implementation: Solaris uscsi, e.g. for SunOS 5.11
PORTING:
Porting libburn typically will consist of adding a new operating system case
to the following switcher files:
os.h Operating system specific libburn definitions and declarations.
sg.c Operating system dependent transport level modules.
and of deriving the following system specific files from existing examples:
os-*.h Included by os.h. You will need some general system knowledge
about signals and knowledge about the storage object needs of your
transport level module sg-*.c.
sg-*.c This source module. You will need special system knowledge about
how to detect all potentially available drives, how to open them,
eventually how to exclusively reserve them, how to perform
SCSI transactions, how to inquire the (pseudo-)SCSI driver.
You will not need to care about CD burning, MMC or other high-level
SCSI aspects.
Said sg-*.c operations are defined by a public function interface, which has
to be implemented in a way that provides libburn with the desired services:
sg_id_string() returns an id string of the SCSI transport adapter.
It may be called before initialization but then may
return only a preliminary id.
sg_initialize() performs global initialization of the SCSI transport
adapter and eventually needed operating system
facilities. Checks for compatibility of supporting
software components.
sg_shutdown() performs global finalizations and releases golbally
aquired resources.
sg_give_next_adr() iterates over the set of potentially useful drive
address strings.
scsi_enumerate_drives() brings all available, not-whitelist-banned, and
accessible drives into libburn's list of drives.
sg_dispose_drive() finalizes adapter specifics of struct burn_drive
on destruction. Releases resources which were aquired
underneath scsi_enumerate_drives().
sg_drive_is_open() tells wether libburn has the given drive in use.
sg_grab() opens the drive for SCSI commands and ensures
undisturbed access.
sg_release() closes a drive opened by sg_grab()
sg_issue_command() sends a SCSI command to the drive, receives reply,
and evaluates wether the command succeeded or shall
be retried or finally failed.
sg_obtain_scsi_adr() tries to obtain SCSI address parameters.
burn_os_is_2k_seekrw() tells whether the given path leads to a file object
that can be used in 2 kB granularity by lseek(2),
read(2), and possibly write(2) if not read-only..
E.g. a USB stick or a hard disk.
burn_os_stdio_capacity() estimates the emulated media space of stdio-drives.
burn_os_open_track_src() opens a disk file in a way that allows best
throughput with file reading and/or SCSI write command
transmission.
burn_os_alloc_buffer() allocates a memory area that is suitable for file
descriptors issued by burn_os_open_track_src().
The buffer size may be rounded up for alignment
reasons.
burn_os_free_buffer() delete a buffer obtained by burn_os_alloc_buffer().
Porting hints are marked by the text "PORTING:".
Send feedback to libburn-hackers@pykix.org .
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
/** PORTING : ------- OS dependent headers and definitions ------ */
#include <unistd.h>
#include <stropts.h>
#include <stdio.h>
#include <sys/types.h>
#include <errno.h>
#include <fcntl.h>
#include <sys/stat.h>
#include <string.h>
#include <stdlib.h>
#include <dirent.h>
#ifdef Libburn_os_has_statvfS
#include <sys/statvfs.h>
#endif /* Libburn_os_has_stavtfS */
#include <sys/dkio.h>
#include <sys/vtoc.h>
#include <sys/scsi/impl/uscsi.h>
/* The waiting time before eventually retrying a failed SCSI command.
Before each retry wait Libburn_sg_linux_retry_incR longer than with
the previous one.
*/
#define Libburn_sg_solaris_retry_usleeP 100000
#define Libburn_sg_solaris_retry_incR 100000
/** PORTING : ------ libburn portable headers and definitions ----- */
#include "transport.h"
#include "drive.h"
#include "sg.h"
#include "spc.h"
#include "sbc.h"
#include "debug.h"
#include "toc.h"
#include "util.h"
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
/* is in portable part of libburn */
int burn_drive_is_banned(char *device_address);
int burn_drive_resolve_link(char *path, char adr[],
int *recursion_count, int flag); /* drive.c */
/* Whether to log SCSI commands:
bit0= log in /tmp/libburn_sg_command_log
bit1= log to stderr
bit2= flush every line
*/
extern int burn_sg_log_scsi;
/* ------------------------------------------------------------------------ */
/* PORTING: Private definitions. Port only if needed by public functions. */
/* (Public functions are listed below) */
/* ------------------------------------------------------------------------ */
/* Storage object is in libburn/init.c
whether to strive for exclusive access to the drive
*/
extern int burn_sg_open_o_excl;
/* ------------------------------------------------------------------------ */
/* PORTING: Private functions. Port only if needed by public functions */
/* (Public functions are listed below) */
/* ------------------------------------------------------------------------ */
static int sg_close_drive(struct burn_drive * d)
{
if (d->fd != -1) {
close(d->fd);
d->fd = -1;
return 1;
}
return 0;
}
static int decode_btl_number(char **cpt, int stopper, int *no)
{
*no = 0;
for ((*cpt)++; **cpt != stopper; (*cpt)++) {
if (**cpt < '0' || **cpt > '9')
return 0;
*no = *no * 10 + **cpt - '0';
}
return 1;
}
/* Read bus, target, lun from name "cXtYdZs2".
Return 0 if name is not of the desired form.
*/
static int decode_btl_solaris(char *name, int *busno, int *tgtno, int *lunno,
int flag)
{
char *cpt;
int ret;
*busno = *tgtno = *lunno = -1;
cpt = name;
if (*cpt != 'c')
return 0;
ret = decode_btl_number(&cpt, 't', busno);
if (ret <= 0)
return ret;
ret = decode_btl_number(&cpt, 'd', tgtno);
if (ret <= 0)
return ret;
ret = decode_btl_number(&cpt, 's', lunno);
if (ret <= 0)
return ret;
cpt++;
if (*cpt != '2' || *(cpt + 1) != 0)
return 0;
return 1;
}
static int start_enum_cXtYdZs2(burn_drive_enumerator_t *idx, int flag)
{
DIR *dir;
idx->dir = NULL;
dir = opendir("/dev/rdsk");
if (dir == NULL) {
libdax_msgs_submit(libdax_messenger, -1,
0x0002000c, LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
"Cannot start device file enumeration. opendir(\"/dev/rdsk\") failed.",
errno, 0);
return 0;
}
idx->dir = dir;
return 1;
}
static int next_enum_cXtYdZs2(burn_drive_enumerator_t *idx,
char adr[], int adr_size, int flag)
{
int busno, tgtno, lunno, ret, fd = -1;
char volpath[160];
struct dirent *entry;
struct dk_cinfo cinfo;
DIR *dir;
dir = idx->dir;
while (1) {
errno = 0;
entry = readdir(dir);
if (entry == NULL) {
if (errno) {
libdax_msgs_submit(libdax_messenger,
-1, 0x0002000d,
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
"Cannot enumerate next device. readdir() from \"/dev/rdsk\" failed.",
errno, 0);
return -1;
}
break;
}
if (strlen(entry->d_name) > sizeof(volpath) - 11)
continue;
ret = decode_btl_solaris(entry->d_name,
&busno, &tgtno, &lunno, 0);
if (ret <= 0)
continue; /* not cXtYdZs2 */
sprintf(volpath, "/dev/rdsk/%s", entry->d_name);
if (burn_drive_is_banned(volpath))
continue;
fd = open(volpath, O_RDONLY | O_NDELAY);
if (fd < 0)
continue;
/* See man dkio */
ret = ioctl(fd, DKIOCINFO, &cinfo);
close(fd);
if (ret < 0)
continue;
if (cinfo.dki_ctype != DKC_CDROM)
continue;
if (adr_size <= strlen(volpath))
return -1;
strcpy(adr, volpath);
return 1;
}
return 0;
}
static int end_enum_cXtYdZs2(burn_drive_enumerator_t *idx, int flag)
{
DIR *dir;
dir = idx->dir;
if(dir != NULL)
closedir(dir);
idx->dir = NULL;
return 1;
}
/* ----------------------------------------------------------------------- */
/* PORTING: Private functions which contain publicly needed functionality. */
/* Their portable part must be performed. So it is probably best */
/* to replace the non-portable part and to call these functions */
/* in your port, too. */
/* ----------------------------------------------------------------------- */
/** Wraps a detected drive into libburn structures and hands it over to
libburn drive list.
*/
static void enumerate_common(char *fname,
int bus_no, int host_no,
int channel_no, int target_no, int lun_no)
{
int ret;
struct burn_drive out;
/* General libburn drive setup */
burn_setup_drive(&out, fname);
/* This transport adapter uses SCSI-family commands and models
(seems the adapter would know better than its boss, if ever) */
ret = burn_scsi_setup_drive(&out, bus_no, host_no, channel_no,
target_no, lun_no, 0);
if (ret <= 0)
return;
/* PORTING: ------------------- non portable part --------------- */
/* Transport adapter is Solaris uscsi */
/* Adapter specific handles and data */
out.fd = -1;
/* PORTING: ---------------- end of non portable part ------------ */
/* Adapter specific functions with standardized names */
out.grab = sg_grab;
out.release = sg_release;
out.drive_is_open = sg_drive_is_open;
out.issue_command = sg_issue_command;
/* Finally register drive and inquire drive information */
burn_drive_finish_enum(&out);
}
/* ------------------------------------------------------------------------ */
/* PORTING: Public functions. These MUST be ported. */
/* ------------------------------------------------------------------------ */
/** Returns the id string of the SCSI transport adapter and eventually
needed operating system facilities.
This call is usable even if sg_initialize() was not called yet. In that
case a preliminary constant message might be issued if detailed info is
not available yet.
@param msg returns id string
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_id_string(char msg[1024], int flag)
{
sprintf(msg, "internal Solaris uscsi adapter sg-solaris");
return 1;
}
/** Performs global initialization of the SCSI transport adapter and eventually
needed operating system facilities. Checks for compatibility of supporting
software components.
@param msg returns ids and/or error messages of eventual helpers
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_initialize(char msg[1024], int flag)
{
return sg_id_string(msg, 0);
}
/** Performs global finalization of the SCSI transport adapter and eventually
needed operating system facilities. Releases globally aquired resources.
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_shutdown(int flag)
{
return 1;
}
/** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
struct burn_drive which are defined in os-*.h.
The eventual initialization of those components was made underneath
scsi_enumerate_drives().
This will be called when a burn_drive gets disposed.
@param d the drive to be finalized
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_dispose_drive(struct burn_drive *d, int flag)
{
return 1;
}
/** Returns the next index number and the next enumerated drive address.
The enumeration has to cover all available and accessible drives. It is
allowed to return addresses of drives which are not available but under
some (even exotic) circumstances could be available. It is on the other
hand allowed, only to hand out addresses which can really be used right
in the moment of this call. (This implementation chooses the latter.)
@param idx An opaque handle. Make no own theories about it.
@param adr Takes the reply
@param adr_size Gives maximum size of reply including final 0
@param initialize 1 = start new,
0 = continue, use no other values for now
-1 = finish
@return 1 = reply is a valid address , 0 = no further address available
-1 = severe error (e.g. adr_size too small)
*/
int sg_give_next_adr(burn_drive_enumerator_t *idx,
char adr[], int adr_size, int initialize)
{
int ret;
if (initialize == 1) {
ret = start_enum_cXtYdZs2(idx, 0);
if (ret <= 0)
return ret;
} else if (initialize == -1) {
ret = end_enum_cXtYdZs2(idx, 0);
return 0;
}
ret = next_enum_cXtYdZs2(idx, adr, adr_size, 0);
return ret;
}
/** Brings all available, not-whitelist-banned, and accessible drives into
libburn's list of drives.
*/
int scsi_enumerate_drives(void)
{
burn_drive_enumerator_t idx;
int initialize = 1, ret, i_bus_no = -1;
int i_host_no = -1, i_channel_no = -1, i_target_no = -1, i_lun_no = -1;
char buf[4096];
while(1) {
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
initialize = 0;
if (ret <= 0)
break;
if (burn_drive_is_banned(buf))
continue;
sg_obtain_scsi_adr(buf, &i_bus_no, &i_host_no,
&i_channel_no, &i_target_no, &i_lun_no);
enumerate_common(buf,
i_bus_no, i_host_no, i_channel_no,
i_target_no, i_lun_no);
}
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
return 1;
}
/** Tells whether libburn has the given drive in use or exclusively reserved.
If it is "open" then libburn will eventually call sg_release() on it when
it is time to give up usage resp. reservation.
*/
/** Published as burn_drive.drive_is_open() */
int sg_drive_is_open(struct burn_drive * d)
{
return (d->fd != -1);
}
/** Opens the drive for SCSI commands and - if burn activities are prone
to external interference on your system - obtains an exclusive access lock
on the drive. (Note: this is not physical tray locking.)
A drive that has been opened with sg_grab() will eventually be handed
over to sg_release() for closing and unreserving.
*/
int sg_grab(struct burn_drive *d)
{
char msg[4096];
int os_errno, ret;
struct dk_cinfo cinfo;
if (d->fd != -1) {
d->released = 0;
return 1;
}
d->fd = open(d->devname, O_RDONLY | O_NDELAY);
if (d->fd == -1) {
os_errno = errno;
sprintf(msg, "Could not grab drive '%s'", d->devname);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020003,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, os_errno, 0);
return 0;
}
ret = ioctl(d->fd, DKIOCINFO, &cinfo);
if (ret < 0)
goto revoke;
if (cinfo.dki_ctype != DKC_CDROM)
goto revoke;
/* >>> obtain eventual locks */;
d->released = 0;
return 1;
revoke:;
sprintf(msg, "Could not grab drive '%s'. Not a CDROM device.",
d->devname);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020003,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
return 0;
}
/** PORTING: Is mainly about the call to sg_close_drive() and whether it
implements the demanded functionality.
*/
/** Gives up the drive for SCSI commands and releases eventual access locks.
(Note: this is not physical tray locking.)
*/
int sg_release(struct burn_drive *d)
{
if (d->fd < 0) {
burn_print(1, "release an ungrabbed drive. die\n");
return 0;
}
sg_close_drive(d);
return 0;
}
/** Sends a SCSI command to the drive, receives reply and evaluates wether
the command succeeded or shall be retried or finally failed.
Returned SCSI errors shall not lead to a return value indicating failure.
The callers get notified by c->error. An SCSI failure which leads not to
a retry shall be notified via scsi_notify_error().
The Libburn_log_sg_commandS facility might be of help when problems with
a drive have to be examined. It shall stay disabled for normal use.
@return: 1 success , <=0 failure
*/
int sg_issue_command(struct burn_drive *d, struct command *c)
{
int i, usleep_time, timeout_ms, no_retry = 0, ret;
time_t start_time;
struct uscsi_cmd cgc;
char msg[80];
static FILE *fp = NULL;
c->error = 0;
memset(c->sense, 0, sizeof(c->sense));
if (d->fd == -1)
return 0;
if (burn_sg_log_scsi & 1) {
if (fp == NULL) {
fp= fopen("/tmp/libburn_sg_command_log", "a");
fprintf(fp,
"\n-----------------------------------------\n");
}
}
if (burn_sg_log_scsi & 3)
scsi_log_cmd(c,fp,0);
memset (&cgc, 0, sizeof (struct uscsi_cmd));
/* No error messages, no retries,
do not execute with other commands, request sense data
*/
cgc.uscsi_flags = USCSI_SILENT | USCSI_DIAGNOSE | USCSI_ISOLATE
| USCSI_RQENABLE;
cgc.uscsi_timeout = 200;
cgc.uscsi_cdb = (caddr_t) c->opcode;
cgc.uscsi_bufaddr = (caddr_t) c->page->data;
if (c->dir == TO_DRIVE) {
cgc.uscsi_flags |= USCSI_WRITE;
cgc.uscsi_buflen = c->page->bytes;
} else if (c->dir == FROM_DRIVE) {
cgc.uscsi_flags |= USCSI_READ;
if (c->dxfer_len >= 0)
cgc.uscsi_buflen = c->dxfer_len;
else
cgc.uscsi_buflen = BUFFER_SIZE;
/* touch page so we can use valgrind */
memset(c->page->data, 0, BUFFER_SIZE);
} else {
cgc.uscsi_buflen = 0;
}
cgc.uscsi_cdblen = c->oplen;
cgc.uscsi_rqlen = sizeof(c->sense);
cgc.uscsi_rqbuf = (caddr_t) c->sense;
/* retry-loop */
start_time = time(NULL);
timeout_ms = 200000;
for(i = 0; ; i++) {
ret = ioctl(d->fd, USCSICMD, &cgc);
/* For cgc.uscsi_status see SAM-3 5.3.1, Table 22
0 = GOOD , 2 = CHECK CONDITION : Sense Data are delivered
8 = BUSY
*/
if (ret != 0 && cgc.uscsi_status != 2) {
sprintf(msg,
"Failed to transfer command to drive. (uscsi_status = 0x%X)",
(unsigned int) cgc.uscsi_status),
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x0002010c,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
msg, errno, 0);
sg_close_drive(d);
d->released = 1;
d->busy = BURN_DRIVE_IDLE;
c->error = 1;
return -1;
}
c->sense[2] &= 15;
/* >>> valid sense: cgc.uscsi_rqlen - cgc.uscsi_rqresid */;
if (c->sense[2] || c->sense[12] || c->sense[13]) {
if (no_retry || !c->retry) {
c->error = 1;
goto ex;
}
switch (scsi_error(d, c->sense, 18)) {
case RETRY:
if (burn_sg_log_scsi & 3) {
/* >>> Need own duration time
measurement. Then remove bit1 */
scsi_log_err(c, fp, c->sense, 0,
(c->error != 0) | 2);
scsi_log_cmd(c,fp,0);
}
break;
case FAIL:
c->error = 1;
goto ex;
}
/*
Calming down retries and breaking up endless cycle
*/
usleep_time = Libburn_sg_solaris_retry_usleeP +
i * Libburn_sg_solaris_retry_incR;
if (time(NULL) + usleep_time / 1000000 - start_time >
timeout_ms / 1000 + 1) {
c->error = 1;
goto ex;
}
usleep(usleep_time);
} else
break; /* retry-loop */
} /* end of retry-loop */
ex:;
if (c->error)
scsi_notify_error(d, c, c->sense, 18, 0);
if (burn_sg_log_scsi & 3)
/* >>> Need own duration time measurement. Then remove bit1 */
scsi_log_err(c, fp, c->sense, 0, (c->error != 0) | 2);
return 1;
}
/** Tries to obtain SCSI address parameters.
@return 1 is success , 0 is failure
*/
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
int *target_no, int *lun_no)
{
int ret;
/* Try to guess from path */
if (strncmp("/dev/rdsk/", path, 10) == 0) {
ret = decode_btl_solaris(path + 10,
bus_no, target_no, lun_no, 0);
if (ret > 0) {
*host_no = *bus_no;
*channel_no = 0;
return 1;
}
}
*bus_no = *host_no = *channel_no = *target_no = *lun_no = -1;
/* >>> Could need a ioctl which gives SCSI numbers */;
return (0);
}
/** Tells wether a text is a persistent address as listed by the enumeration
functions.
*/
int sg_is_enumerable_adr(char* adr)
{
burn_drive_enumerator_t idx;
int initialize = 1, ret;
char buf[64];
while(1) {
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
initialize = 0;
if (ret <= 0)
break;
if (strcmp(adr, buf) == 0) {
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
return 1;
}
}
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
return (0);
}
/* Return 1 if the given path leads to a regular file or a device that can be
seeked, read, and possibly written with 2 kB granularity.
*/
int burn_os_is_2k_seekrw(char *path, int flag)
{
struct stat stbuf;
if (stat(path, &stbuf) == -1)
return 0;
if (S_ISREG(stbuf.st_mode))
return 1;
if (S_ISBLK(stbuf.st_mode))
return 1;
return 0;
}
/** Estimate the potential payload capacity of a file address.
@param path The address of the file to be examined. If it does not
exist yet, then the directory will be inquired.
@param bytes The pointed value gets modified, but only if an estimation is
possible.
@return -2 = cannot perform necessary operations on file object
-1 = neither path nor dirname of path exist
0 = could not estimate size capacity of file object
1 = estimation has been made, bytes was set
*/
int burn_os_stdio_capacity(char *path, off_t *bytes)
{
struct stat stbuf;
#ifdef Libburn_os_has_statvfS
struct statvfs vfsbuf;
#endif
char testpath[4096], *cpt;
long blocks;
off_t add_size = 0;
testpath[0] = 0;
blocks = *bytes / 512;
if (stat(path, &stbuf) == -1) {
strcpy(testpath, path);
cpt = strrchr(testpath, '/');
if(cpt == NULL)
strcpy(testpath, ".");
else if(cpt == testpath)
testpath[1] = 0;
else
*cpt = 0;
if (stat(testpath, &stbuf) == -1)
return -1;
} else if(S_ISBLK(stbuf.st_mode)) {
int open_mode = O_RDONLY, fd;
fd = open(path, open_mode);
if (fd == -1)
return -2;
*bytes = lseek(fd, 0, SEEK_END);
close(fd);
if (*bytes == -1) {
*bytes = 0;
return 0;
}
} else if(S_ISREG(stbuf.st_mode)) {
add_size = stbuf.st_blocks * (off_t) 512;
strcpy(testpath, path);
} else
return 0;
if (testpath[0]) {
#ifdef Libburn_os_has_statvfS
if (statvfs(testpath, &vfsbuf) == -1)
return -2;
*bytes = add_size + ((off_t) vfsbuf.f_frsize) *
(off_t) vfsbuf.f_bavail;
#else /* Libburn_os_has_statvfS */
return 0;
#endif /* ! Libburn_os_has_stavtfS */
}
return 1;
}
/* ts A91122 : an interface to open(O_DIRECT) or similar OS tricks. */
#ifdef Libburn_read_o_direcT
/* No special O_DIRECT-like precautions are implemented here */
#endif /* Libburn_read_o_direcT */
int burn_os_open_track_src(char *path, int open_flags, int flag)
{
int fd;
fd = open(path, open_flags);
return fd;
}
void *burn_os_alloc_buffer(size_t amount, int flag)
{
void *buf = NULL;
buf = calloc(1, amount);
return buf;
}
int burn_os_free_buffer(void *buffer, size_t amount, int flag)
{
if (buffer == NULL)
return 0;
free(buffer);
return 1;
}

View File

@ -1,17 +1,71 @@
/* sg.c
Switcher for operating system dependent transport level modules of libburn.
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
Copyright (C) 2009 - 2010 Thomas Schmitt <scdbackup@gmx.net>,
provided under GPLv2+
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#undef HAVE_CONFIG_H
#endif
#ifdef Libburn_use_sg_dummY
#include "sg-dummy.c"
#else
#ifdef Libburn_use_libcdiO
#include "sg-libcdio.c"
#else
#ifdef __FreeBSD__
#include "sg-freebsd.c"
#else
#ifdef __FreeBSD_kernel__
#include "sg-freebsd.c"
#else
#ifdef __linux
#include "sg-linux.c"
#endif
#else
#ifdef __sun
#include "sg-solaris.c"
#else
/* The dummy adapter formally fulfills the expectations of libburn towards
its SCSI command transport. It will show no drives and perform no SCSI
commands.
libburn will then be restricted to using its stdio pseudo drives.
*/
static int intentional_compiler_warning(void)
{
int INTENTIONAL_COMPILER_WARNING_;
int Cannot_recognize_GNU_Linux_nor_FreeBSD_;
int Have_to_use_dummy_MMC_transport_adapter_;
int This_libburn_will_not_be_able_to_operate_on_real_CD_drives;
int Have_to_use_dummy_MMC_transport_adapter;
int Cannot_recognize_GNU_Linux_nor_FreeBSD;
int INTENTIONAL_COMPILER_WARNING;
return(0);
}
#include "sg-dummy.c"
#endif /* ! __sun */
#endif /* ! __linux */
#endif /* ! __FreeBSD_kernel__ */
#endif /* ! __FreeBSD__ */
#endif /* ! Libburn_use_libcdiO */
#endif /* ! Libburn_use_sg_dummY */

View File

@ -1,5 +1,8 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (C) 2009 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
*/
#ifndef __SG
#define __SG
@ -31,6 +34,51 @@ int scsi_enumerate_drives(void);
int sg_drive_is_open(struct burn_drive * d);
int burn_os_is_2k_seekrw(char *path, int flag);
int burn_os_stdio_capacity(char *path, off_t *bytes);
/* ts A91227 */
/** Returns the id string of the SCSI transport adapter and eventually
needed operating system facilities.
This call is usable even if sg_initialize() was not called yet. In that
case a preliminary constant message might be issued if detailed info is
not available yet.
@param msg returns id string
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_id_string(char msg[1024], int flag);
/* ts A91225 */
/** Performs global initialization of the SCSI transport adapter and eventually
needed operating system facilities. Checks for compatibility supporting
software components.
@param msg returns ids and/or error messages of eventual helpers
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_initialize(char msg[1024], int flag);
/* ts A91227 */
/** Performs global finalization of the SCSI transport adapter and eventually
needed operating system facilities. Releases globally aquired resources.
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_shutdown(int flag);
/* ts A91227 */
/** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
struct burn_drive which are defined in os-*.h.
The eventual initialization of those components was made underneath
scsi_enumerate_drives().
This will be called when a burn_drive gets disposed.
@param d the drive to be finalized
@param flag unused yet, submit 0
@return 1 = success, <=0 = failure
*/
int sg_dispose_drive(struct burn_drive *d, int flag);
#endif /* __SG */

View File

@ -1,5 +1,15 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <stdlib.h>
#include <string.h>
#include "libburn.h"

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,11 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifndef __SPC
#define __SPC
@ -59,4 +65,20 @@ int scsi_notify_error(struct burn_drive *, struct command *c,
/* ts A70519 */
int scsi_init_command(struct command *c, unsigned char *opcode, int oplen);
/* ts A91106 */
int scsi_show_cmd_text(struct command *c, void *fp, int flag);
/* ts A91106 */
int scsi_show_cmd_reply(struct command *c, void *fp, int flag);
/* ts A91218 (former sg_log_cmd ts A70518) */
/** Logs command (before execution) */
int scsi_log_cmd(struct command *c, void *fp, int flag);
/* ts A91221 (former sg_log_err ts A91108) */
/** Logs outcome of a sg command. */
int scsi_log_err(struct command *c, void *fp, unsigned char sense[18],
int duration, int flag);
#endif /*__SPC*/

View File

@ -1,4 +1,13 @@
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
/* ts A61008 */
/* #include <a ssert.h> */
@ -104,6 +113,30 @@ int burn_disc_add_session(struct burn_disc *d, struct burn_session *s,
return 1;
}
/* ts A81202: this function was in the API but not implemented.
*/
int burn_disc_remove_session(struct burn_disc *d, struct burn_session *s)
{
int i, skip = 0;
if (d->session == NULL)
return 0;
for (i = 0; i < d->sessions; i++) {
if (s == d->session[i]) {
skip++;
continue;
}
d->session[i - skip] = d->session[i];
}
if (!skip)
return 0;
burn_session_free(s);
d->sessions--;
return 1;
}
struct burn_track *burn_track_create(void)
{
struct burn_track *t;
@ -257,13 +290,23 @@ void burn_track_define_data(struct burn_track *t, int offset, int tail,
/* ts A61024 */
int burn_track_set_byte_swap(struct burn_track *t, int swap_source_bytes)
{
if(swap_source_bytes!=0 && swap_source_bytes!=1)
if (swap_source_bytes != 0 && swap_source_bytes != 1)
return 0;
t->swap_source_bytes = swap_source_bytes;
return 1;
}
/* ts A90911 : API */
int burn_track_set_cdxa_conv(struct burn_track *t, int value)
{
if (value < 0 || value > 1)
return 0;
t->cdxa_conversion = value;
return 1;
}
void burn_track_set_isrc(struct burn_track *t, char *country, char *owner,
unsigned char year, unsigned int serial)
{
@ -334,6 +377,11 @@ int burn_track_get_sectors(struct burn_track *t)
int sectors, seclen;
seclen = burn_sector_length(t->mode);
if (t->cdxa_conversion == 1)
/* ts A90911 : will read blocks of 2056 bytes and write 2048 */
seclen += 8;
if (t->source != NULL) /* ts A80808 : mending sigsegv */
size = t->offset + t->source->get_size(t->source) + t->tail;
else if(t->entry != NULL) {
@ -529,14 +577,53 @@ int burn_session_get_hidefirst(struct burn_session *session)
/* ts A80808 : Enhance CD toc to DVD toc */
int burn_disc_cd_toc_extensions(struct burn_disc *d, int flag)
{
int sidx, tidx;
int sidx= 0, tidx= 0;
struct burn_toc_entry *entry, *prev_entry= NULL;
/* ts A81126 : ticket 146 : There was a SIGSEGV in here */
char msg_data[321], *msg;
strcpy(msg_data,
"Damaged CD table-of-content detected and truncated.");
strcat(msg_data, " In burn_disc_cd_toc_extensions: ");
msg = msg_data + strlen(msg_data);
if (d->session == NULL) {
strcpy(msg, "d->session == NULL");
goto failure;
}
for (sidx = 0; sidx < d->sessions; sidx++) {
if (d->session[sidx] == NULL) {
sprintf(msg, "d->session[%d of %d] == NULL",
sidx, d->sessions);
goto failure;
}
if (d->session[sidx]->track == NULL) {
sprintf(msg, "d->session[%d of %d]->track == NULL",
sidx, d->sessions);
goto failure;
}
if (d->session[sidx]->leadout_entry == NULL) {
sprintf(msg,
" Session %d of %d: Leadout entry missing.",
sidx, d->sessions);
goto failure;
}
for (tidx = 0; tidx < d->session[sidx]->tracks + 1; tidx++) {
if (tidx < d->session[sidx]->tracks)
if (tidx < d->session[sidx]->tracks) {
if (d->session[sidx]->track[tidx] == NULL) {
sprintf(msg,
"d->session[%d of %d]->track[%d of %d] == NULL",
sidx, d->sessions, tidx, d->session[sidx]->tracks);
goto failure;
}
entry = d->session[sidx]->track[tidx]->entry;
else
if (entry == NULL) {
sprintf(msg,
"session %d of %d, track %d of %d, entry == NULL",
sidx, d->sessions, tidx,
d->session[sidx]->tracks);
goto failure;
}
} else
entry = d->session[sidx]->leadout_entry;
entry->session_msb = 0;
entry->point_msb = 0;
@ -558,6 +645,11 @@ int burn_disc_cd_toc_extensions(struct burn_disc *d, int flag)
}
}
return 1;
failure:
libdax_msgs_submit(libdax_messenger, -1, 0x0002015f,
LIBDAX_MSGS_SEV_MISHAP, LIBDAX_MSGS_PRIO_HIGH, msg_data, 0, 0);
d->sessions= sidx;
return 0;
}

View File

@ -1,3 +1,9 @@
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifndef BURN__STRUCTURE_H
#define BURN__STRUCTURE_H
@ -64,6 +70,10 @@ struct burn_track
/* ts A61024 */
/** Byte swapping on source data stream : 0=none , 1=pairwise */
int swap_source_bytes;
/* ts A90910 : conversions from CD XA prepared input */
int cdxa_conversion; /* 0=none, 1=remove -xa1 headers (first 8 bytes)*/
};
struct burn_session

View File

@ -1,5 +1,14 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
/* ts A61008 */
/* #include <a ssert.h> */
@ -130,7 +139,7 @@ void toc_find_modes(struct burn_drive *d)
} else {
t->mode = BURN_MODE1;
/* ts A70519 : this does not work with Linux 2.4 USB because one cannot
/* ts A70519 : this does not work with GNU/Linux 2.4 USB because one cannot
predict the exact dxfer_size without knowing the sector type.
mem.sectors = 1;
d->read_sectors(d, lba, mem.sectors, &o, &mem);

View File

@ -1,5 +1,10 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Provided under GPL version 2 or later.
*/
#ifndef __TOC_H
#define __TOC_H

View File

@ -1,5 +1,11 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifndef __TRANSPORT
#define __TRANSPORT
@ -40,7 +46,9 @@ struct buffer
Added 4096 bytes reserve against possible buffer overflows.
(Changed in sector.c buffer flush test from >= to > BUFFER_SIZE .
This can at most cause a 1 sector overlap. Sometimes an offset
of 16 byte is applied to the output data (in some RAW mode). ) */
of 16 byte is applied to the output data (in some RAW mode). )
burn_write_opts.cdxa_conversion can imply an offset of 8 bytes.
*/
unsigned char data[BUFFER_SIZE + 4096];
int sectors;
int bytes;
@ -161,6 +169,11 @@ struct burn_drive
char current_profile_text[80];
int current_is_cd_profile;
int current_is_supported_profile;
/* ts A90603 */
int current_is_guessed_profile;
/* ts A90815 */
unsigned char all_profiles[256];
int num_profiles;
/* ts A70128 : MMC-to-MMC feature info from 46h for DVD-RW.
Quite internal. Regard as opaque :)
@ -171,6 +184,19 @@ struct burn_drive
/* Link Size item number 0 from feature 0021h descriptor */
int current_feat21h_link_size;
/* Flags from feature 0023h for formatting BD mmc5r03c.pdf 5.3.13
Byte 4 BD-RE:
bit0= Cert format 30h sub-type 10b
bit1= QCert format 30h sub-type 11b
bit2= Expand format 01h
bit3= RENoSA format 31h
Byte 8 BD-R:
bit0= RRM format 32h sub-type 10b
*/
int current_feat23h_byte4;
int current_feat23h_byte8;
/* Flags from feature 002Fh feature descriptor mmc5r03c.pdf 5.3.25 :
bit1= DVD-RW supported
bit2= Test Write available
@ -192,8 +218,25 @@ struct burn_drive
with BD-RE */
int do_stream_recording;
/* ts A90227 : the LBA where stream recording shall start.
Writing to lower LBA will be done without streaming.
*/
int stream_recording_start;
/* ts A61218 from 51h READ DISC INFORMATION */
int last_lead_in;
int last_lead_out;
int num_opc_tables; /* ts A91104: -1= not yet known */
int bg_format_status; /* 0=needs format start, 1=needs format restart*/
int disc_type; /* 0="CD-DA or CD-ROM", 0x10="CD-I", 0x20="CD-ROM XA" */
unsigned int disc_id; /* a "32 bit binary integer" */
char disc_bar_code[9];
int disc_app_code;
int disc_info_valid; /* bit0= disc_type , bit1= disc_id ,
bit2= disc_bar_code , bit3= disc_app_code
bit4= URU bit is set (= unrestricted use)
bit5= Erasable bit was set in reply
*/
/* ts A70108 from 23h READ FORMAT CAPACITY mmc5r03c.pdf 6.24 */
int format_descr_type; /* 1=unformatted, 2=formatted, 3=unclear */
@ -223,6 +266,9 @@ struct burn_drive
/* ts A70131 : from 51h READ DISC INFORMATION Number of Sessions (-1)*/
int complete_sessions;
/* ts A90107 */
int state_of_last_session;
/* ts A70129 :
from 51h READ DISC INFORMATION Last Track Number in Last Session */
int last_track_no;
@ -235,6 +281,9 @@ struct burn_drive
/* ts A70215 : if > 0 : first lba on media that is too high for write*/
int media_lba_limit;
/* ts A81210 : Upper limit of readable data size,
0x7fffffff = unknown */
int media_read_capacity;
int toc_temp;
struct burn_disc *disc; /* disc structure */
@ -263,6 +312,8 @@ struct burn_drive
/* ts A70929 */
pid_t thread_pid;
int thread_pid_valid;
/* ts B00225 */
pthread_t thread_tid;
/* transport functions */
@ -288,6 +339,11 @@ struct burn_drive
void (*eject) (struct burn_drive *);
void (*load) (struct burn_drive *);
int (*start_unit) (struct burn_drive *);
/* ts A90824 : Calming down noisy drives */
int (*stop_unit) (struct burn_drive *);
int is_stopped;
void (*read_disc_info) (struct burn_drive *);
void (*read_sectors) (struct burn_drive *,
int start,

View File

@ -1,10 +1,25 @@
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <string.h>
/* ts A61008 */
/* #include <a ssert.h> */
#include <stdlib.h>
#include "../version.h"
#include <stdio.h>
/* ts A80914 : This is unneeded. Version info comes from libburn.h.
#include "v ersion.h"
*/
#include "util.h"
#include "libburn.h"
@ -48,13 +63,272 @@ char *burn_strndup(char *s, int n)
void burn_version(int *major, int *minor, int *micro)
{
/* ts A80408 : switched from configure.ac versioning to libburn.h versioning */
#ifdef burn_header_version_major
*major = burn_header_version_major;
*minor = burn_header_version_minor;
*micro = burn_header_version_micro;
#else
*major = BURN_MAJOR_VERSION;
*minor = BURN_MINOR_VERSION;
*micro = BURN_MICRO_VERSION;
#endif
*major = burn_header_version_major;
*minor = burn_header_version_minor;
*micro = burn_header_version_micro;
}
struct cd_mid_record {
char *manufacturer;
int m_li;
int s_li;
int f_li;
int m_lo;
int s_lo;
int f_lo;
char *other_brands;
};
typedef struct cd_mid_record cd_mid_record_t;
/* ts A90902 */
/** API
@param flag Bitfield for control purposes,
bit0= append "(aka %s)",other_brands to reply
*/
char *burn_guess_cd_manufacturer(int m_li, int s_li, int f_li,
int m_lo, int s_lo, int f_lo, int flag)
{
static cd_mid_record_t mid_list[]= {
{"SKC", 96, 40, 0, 0, 0, 0, ""},
{"Ritek Corp" , 96, 43, 30, 0, 0, 0, ""},
{"TDK / Ritek" , 97, 10, 0, 0, 0, 0, "TRAXDATA"},
{"TDK Corporation" , 97, 15, 0, 0, 0, 0, ""},
{"Ritek Corp" , 97, 15, 10, 0, 0, 0, "7-plus, Aopen, PONY, Power Source, TDK, TRAXDATA, HiCO, PHILIPS, Primdisc, Victor.JVC, OPTI STORAGE, Samsung"},
{"Mitsubishi Chemical Corporation" , 97, 15, 20, 0, 0, 0, ""},
{"Nan-Ya Plastics Corporation" , 97, 15, 30, 0, 0, 0, "Hatron, MMore, Acer, LITEON"},
{"Delphi" , 97, 15, 50, 0, 0, 0, ""},
{"Shenzhen SG&SAST" , 97, 16, 20, 0, 0, 0, ""},
{"Moser Baer India Limited" , 97, 17, 0, 0, 0, 0, "EMTEC, Intenso, YAKUMO, PLATINUM, Silver Circle"},
{"SKY media Manufacturing SA" , 97, 17, 10, 0, 0, 0, ""},
{"Wing" , 97, 18, 10, 0, 0, 0, ""},
{"DDT" , 97, 18, 20, 0, 0, 0, ""},
{"Daxon Technology Inc. / Acer" , 97, 22, 60, 0, 0, 0, "Maxmax, Diamond Data, BenQ, gold, SONY"},
{"Taiyo Yuden Company Limited" , 97, 24, 0, 0, 0, 0, "Maxell, FUJIFILM, SONY"},
{"Sony Corporation" , 97, 24, 10, 0, 0, 0, "LeadData, Imation"},
{"Computer Support Italcard s.r.l" , 97, 24, 20, 0, 0, 0, ""},
{"Unitech Japan Inc." , 97, 24, 30, 0, 0, 0, ""},
{"MPO, France" , 97, 25, 0, 0, 0, 0, "TDK"},
{"Hitachi Maxell Ltd." , 97, 25, 20, 0, 0, 0, ""},
{"Infodisc Technology Co,Ltd." , 97, 25, 30, 0, 0, 0, "MEMOREX, SPEEDA, Lead data"},
{"Xcitec" , 97, 25, 60, 0, 0, 0, ""},
{"Fornet International Pte Ltd" , 97, 26, 0, 0, 0, 0, "COMPUSA, Cdhouse"},
{"Postech Corporation" , 97, 26, 10, 0, 0, 0, "Mr.Platinum"},
{"SKC Co Ltd." , 97, 26, 20, 0, 0, 0, "Infinite"},
{"Fuji Photo Film Co,Ltd." , 97, 26, 40, 0, 0, 0, ""},
{"Lead Data Inc." , 97, 26, 50, 0, 0, 0, "SONY, Gigastorage, MIRAGE"},
{"CMC Magnetics Corporation" , 97, 26, 60, 0, 0, 0, "Daxon, Verbatim, Memorex, Bi-Winner, PLEXTOR, YAMAHA, Melody, Office DEPOT, Philips, eMARK, imation, HyperMedia, Samsung, Shintaro, Techworks"},
{"Ricoh Company Limited" , 97, 27, 0, 0, 0, 0, "Sony, Digital Storage, Csita"},
{"Plasmon Data Systems Ltd" , 97, 27, 10, 0, 0, 0, "Ritek, TDK, EMTEC, ALPHAPET, MANIA"},
{"Princo Corporation" , 97, 27, 20, 0, 0, 0, ""},
{"Pioneer" , 97, 27, 30, 0, 0, 0, ""},
{"Eastman Kodak Company" , 97, 27, 40, 0, 0, 0, ""},
{"Mitsui Chemicals Inc." , 97, 27, 50, 0, 0, 0, "MAM-A, TDK"},
{"Ricoh Company Limited" , 97, 27, 60, 0, 0, 0, "Ritek"},
{"Gigastorage Corporation" , 97, 28, 10, 0, 0, 0, "MaxMax, Nan-Ya"},
{"Multi Media Masters&Machinary SA" , 97, 28, 20, 0, 0, 0, "King, Mmirex"},
{"Ritek Corp" , 97, 31, 0, 0, 0, 0, "TDK"},
{"Grand Advance Technology Sdn. Bhd." , 97, 31, 30, 0, 0, 0, ""},
{"TDK Corporation" , 97, 32, 00, 0, 0, 0, ""},
{"Prodisc Technology Inc." , 97, 32, 10, 0, 0, 0, "Smartbuy, Mitsubishi, Digmaster, LG, Media Market"},
{"Mitsubishi Chemical Corporation" , 97, 34, 20, 0, 0, 0, "YAMAHA, Verbatim"},
{"Mitsui Chemicals Inc." , 97, 48, 50, 0, 0, 0, ""},
{"TDK Corporation" , 97, 49, 0, 0, 0, 0, ""},
{"", 0, 0, 0, 0, 0, 0, ""}
};
int i, f_li_0;
char buf[1024];
char *result = NULL;
if (m_li == 0 && s_li == 2 && f_li == 0) {
result = strdup("(no manufacturer code)");
return result;
}
f_li_0 = f_li - (f_li % 10);
for (i = 0; mid_list[i].manufacturer[0]; i++) {
if (m_li == mid_list[i].m_li &&
s_li == mid_list[i].s_li &&
(f_li_0 == mid_list[i].f_li || f_li == mid_list[i].f_li))
break;
}
if (mid_list[i].manufacturer[0] == 0) {
sprintf(buf, "Unknown CD manufacturer. Please report code '%2.2dm%2.2ds%2.2df/%2.2dm%2.2ds%2.2df', the human readable brand, size, and speed to scdbackup@gmx.net.", m_li, s_li, f_li, m_lo, s_lo, f_lo);
result = strdup(buf);
return result;
}
/* Compose, allocate and copy result */
if ((flag & 1) && mid_list[i].other_brands[0]) {
sprintf(buf, "%s (aka %s)",
mid_list[i].manufacturer, mid_list[i].other_brands);
result = strdup(buf);
} else
result = strdup(mid_list[i].manufacturer);
return result;
}
/* ts A90904 */
struct dvd_mid_record {
char *mc1;
char *mc2;
int mc1_sig_len;
char *manufacturer;
};
typedef struct dvd_mid_record dvd_mid_record_t;
/* ts A90904 */
char *burn_guess_manufacturer(int prf,
char *media_code1, char *media_code2, int flag)
{
int i, l = 0, m_li, s_li, f_li, m_lo, s_lo, f_lo;
char buf[1024];
char *result = NULL, *cpt;
/* Important Note: media_code1 and media_code2 are supposed to be
encoded by burn_util_make_printable_word().
Especially: ' ' -> '_' , {"_%/" unprintables -> %XY)
*/
static dvd_mid_record_t mid_list[]= {
{"AML", "", 8, "UML"},
{"BeAll", "", 5, "BeAll Developers, Inc."},
{"CMC", "", 3, "CMC Magnetics Corporation"},
{"DAXON", "", 5, "Daxon Technology Inc. / Acer"},
{"Daxon", "", 5, "Daxon Technology Inc. / Acer"},
{"FUJI", "", 4, "Fujifilm Holdings Corporation"},
{"INFODISC", "", 8, "New Star Digital Co., Ltd."},
{"INFOME", "", 6, "InfoMedia Inc."},
{"ISMMBD", "", 6, "Info Source Multi Media Ltd."},
{"JVC", "", 3, "JVC Limited"},
{"KIC01RG", "", 7, "AMC"},
{"LD", "", 8, "Lead Data Inc."},
{"LGE", "", 3, "LG Electronics"},
{"MAM", "", 8, "Mitsui Advanced Media, Inc. Europe"},
{"MAXELL", "", 6, "Hitachi Maxell Ltd."},
{"MBI", "", 3, "Moser Baer India Limited"},
{"MCC", "", 8, "Mitsubishi Chemical Corporation"},
{"MCI", "", 8, "Mitsui Chemicals Inc."},
{"MEI", "", 3, "Panasonic Corporation"},
{"MKM", "", 3, "Mitsubishi Kagaku Media Co."},
{"MMC", "", 8, "Mitsubishi Kagaku Media Co."},
{"MXL", "", 8, "Hitachi Maxell Ltd."},
{"NANYA", "", 5, "Nan-Ya Plastics Corporation"},
{"NSD", "", 8, "NESA International Inc."},
{"OPTODISC", "", 8, "Optodisc Technology Corporation"},
{"OTCBDR", "", 8, "Optodisc Technology Corporation"},
{"PHILIP", "", 8, "Moser Baer India Limited"},
{"PHILIPS", "", 8, "Philips"},
{"PRINCO", "", 6, "Princo Corporation"},
{"PRODISC", "", 7, "Prodisc Technology Inc."},
{"Prodisc", "", 7, "Prodisc Technology Inc."},
{"PVC", "", 3, "Pioneer"},
{"RICOHJPN", "", 8, "Ricoh Company Limited"},
{"RITEK", "", 5, "Ritek Corp"},
{"SONY", "", 4, "Sony Corporation"},
{"TDK", "", 3, "TDK Corporation"},
{"TT", "", 8, "TDK Corporation"},
{"TY", "", 8, "Taiyo Yuden Company Limited"},
{"TYG", "", 3, "Taiyo Yuden Company Limited"},
{"UTJR001", "", 7, "Unifino Inc."},
{"VERBAT", "", 5, "Mitsubishi Kagaku Media Co."},
{"YUDEN", "", 5, "Taiyo Yuden Company Limited"},
{"", "", 0, ""}
};
if (media_code2 != NULL &&
(prf == -1 || prf == 0x09 || prf == 0x0A)) {
if (strlen(media_code2) == 9 && media_code1[0] == '9' &&
media_code1[2] == 'm' && media_code1[5] == 's' &&
media_code1[8] == 'f' &&
strchr(media_code1, '%') == NULL) {
sscanf(media_code1, "%dm%ds%df", &m_li, &s_li, &f_li);
sscanf(media_code2, "%dm%ds%df", &m_lo, &s_lo, &f_lo);
if (m_li >= 96 && m_li <= 97 && m_lo > 0) {
result = burn_guess_cd_manufacturer(
m_li, s_li, f_li, m_lo, s_lo, f_lo, 0);
return result;
}
}
}
/* DVD-R do not keep manufacturer id apart from media id.
Some manufacturers use a blank as separator which would now be '_'.
*/
cpt = strchr(media_code1, '_');
if (cpt != NULL && (prf == -1 || prf == 0x11 || prf == 0x13 ||
prf == 0x14 || prf == 0x15))
l = cpt - media_code1;
for (i = 0; mid_list[i].mc1[0]; i++) {
if (strncmp(mid_list[i].mc1, media_code1,
mid_list[i].mc1_sig_len) == 0)
break;
if (l > 0)
if (strncmp(mid_list[i].mc1, media_code1, l) == 0)
break;
}
if (mid_list[i].mc1[0] == 0) {
sprintf(buf, "Unknown DVD/BD manufacturer. Please report code '%s/%s', the human readable brand, size, and speed to scdbackup@gmx.net.",
media_code1, media_code2);
result = strdup(buf);
return result;
}
result = strdup(mid_list[i].manufacturer);
return result;
}
/* ts A90905 */
/* Make *text a single printable word */
/* IMPORTANT: text must be freeable memory !
@param flag bit0=escape '/' too
bit1=(overrides bit0) do not escape " _/"
*/
int burn_util_make_printable_word(char **text, int flag)
{
int i, esc_add = 0, ret;
char *wpt, *rpt, *new_text = NULL;
if (flag & 2)
flag &= ~1;
for (i = 0; (*text)[i]; i++) {
rpt = (*text) + i;
if (*rpt < 32 || *rpt > 126 || *rpt == 96 ||
((*rpt == '_' || *rpt == '%') && (!(flag & 2))) ||
(*rpt == '/' && (flag & 1)))
esc_add += 2;
}
if (esc_add) {
new_text = calloc(strlen(*text) + esc_add + 1, 1);
if (new_text == NULL) {
ret = -1;
goto ex;
}
wpt = new_text;
for (i = 0; (*text)[i]; i++) {
rpt = (*text) + i;
if (*rpt < 32 || *rpt > 126 || *rpt == 96 ||
((*rpt == '_' || *rpt == '%') && (!(flag & 2))) ||
(*rpt == '/' && (flag & 1))) {
sprintf(wpt, "%%%2.2X",
(unsigned int) *((unsigned char *) rpt));
wpt+= 3;
} else
*(wpt++) = *rpt;
}
*wpt = 0;
free(*text);
*text = new_text;
}
if (!(flag & 2))
for (i = 0; (*text)[i]; i++)
if ((*text)[i] == ' ')
(*text)[i] = '_';
ret = 1;
ex:
return ret;
}

View File

@ -5,4 +5,7 @@ char *burn_strdup(char *s);
char *burn_strndup(char *s, int n);
/* ts A90905 */
int burn_util_make_printable_word(char **text, int flag);
#endif

View File

@ -1,5 +1,15 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifdef HAVE_CONFIG_H
#include "../config.h"
#endif
#include <unistd.h>
#include <signal.h>
@ -33,10 +43,8 @@
#include "libburn.h"
#include "drive.h"
#include "transport.h"
#include "crc.h"
#include "debug.h"
#include "init.h"
#include "lec.h"
#include "toc.h"
#include "util.h"
#include "sg.h"
@ -44,11 +52,19 @@
#include "options.h"
#include "structure.h"
#include "source.h"
#include "mmc.h"
#include "spc.h"
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
/* ts A91120 : <<< experimental */
#ifdef Libburn_mmap_write_buffeR
#include <sys/mman.h>
#endif
/* The maximum output size to be used with CD media. This is also curbed
by BURN_OS_TRANSPORT_BUFFER_SIZE. The smaller number gets into effect.
*/
@ -770,8 +786,18 @@ int burn_write_track(struct burn_write_opts *o, struct burn_session *s,
libdax_msgs_submit(libdax_messenger, d->global_index, 0x000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
msg, 0, 0);
if (nwa > d->nwa)
d->nwa = nwa;
/* ts A91003 */
if (nwa < d->nwa) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020173,
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
"Drive tells NWA smaller than last written address",
0, 0);
d->sync_cache(d);
return 0;
}
d->nwa = nwa;
}
@ -868,8 +894,19 @@ ex:;
d->sync_cache(d);
/* ts A61030 */
if (burn_write_close_track(o, s, tnum) <= 0)
ret = 0;
/* ts A91003 :
At least in simulation mode this causes NWA=0 for the
next track. cdrecord does not use CLOSE TRACK at all but
ends the tracks by SYNCHRONIZE CACHE alone.
*/
/* ts A91202 :
Peng Shao reports that his LG GH22LS30 issues an SCSI error
on CLOSE TRACK even in non-dummy mode. So i better give up
this gesture which seems not be needed by any drive.
if (!o->simulate)
if (burn_write_close_track(o, s, tnum) <= 0)
ret = 0;
*/
}
return ret;
}
@ -884,8 +921,8 @@ int burn_disc_write_is_ok(struct burn_write_opts *o, struct burn_disc *disc,
for (i = 0; i < disc->sessions; i++)
for (t = 0; t < disc->session[i]->tracks; t++)
if (!sector_headers_is_ok(
o, disc->session[i]->track[t]->mode))
if (sector_headers_is_ok(
o, disc->session[i]->track[t]->mode) != 1)
goto bad_track_mode_found;
return 1;
bad_track_mode_found:;
@ -909,6 +946,8 @@ int burn_disc_init_write_status(struct burn_write_opts *o,
d->cancel = 0;
#ifdef Libburn_reset_progress_asynC
/* <<< This is now done in async.c */
/* init progress before showing the state */
d->progress.session = 0;
d->progress.sessions = disc->sessions;
@ -923,6 +962,7 @@ int burn_disc_init_write_status(struct burn_write_opts *o,
d->progress.sectors = 0;
d->progress.sector = 0;
d->progress.track = 0;
#endif /* Libburn_reset_progress_asynC */
/* ts A61023 */
d->progress.buffer_capacity = 0;
@ -1005,8 +1045,10 @@ int burn_precheck_write(struct burn_write_opts *o, struct burn_disc *disc,
} else if (d->drive_role == 3 ||
d->current_profile == 0x11 || d->current_profile == 0x14 ||
d->current_profile == 0x15 ||
d->current_profile == 0x1b || d->current_profile == 0x2b ) {
/* DVD-R* Sequential , DVD+R[/DL] , sequential stdio "drive" */
d->current_profile == 0x1b || d->current_profile == 0x2b ||
d->current_profile == 0x41) {
/* DVD-R* Sequential , DVD+R[/DL] , BD-R,
sequential stdio "drive" */
if (o->start_byte >= 0)
strcat(reasons, "write start address not supported, ");
} else {
@ -1063,11 +1105,25 @@ int burn_disc_open_track_dvd_minus_r(struct burn_write_opts *o,
/* ts A70214 : eventually adjust already expanded size of track */
burn_track_apply_fillup(s->track[tnum], d->media_capacity_remaining,1);
#ifdef Libburn_pioneer_dvr_216d_with_opC
fprintf(stderr, "libburn_DEBUG: Libburn_pioneer_dvr_216d_with_opC : num_opc_tables = %d\n", d->num_opc_tables);
if (d->num_opc_tables <= 0 && !o->simulate) {
fprintf(stderr, "libburn_DEBUG: Libburn_pioneer_dvr_216d_with_opC : performing OPC\n");
d->perform_opc(d);
fprintf(stderr, "libburn_DEBUG: Libburn_pioneer_dvr_216d_with_opC : done\n");
}
#endif
#ifdef Libburn_pioneer_dvr_216d_get_evenT
mmc_get_event(d);
#endif
if (o->write_type == BURN_WRITE_SAO) { /* DAO */
/* Round track size up to 32 KiB and reserve track */
/* Round track size up to write chunk size and reserve track */
size = ((off_t) burn_track_get_sectors(s->track[tnum]))
* (off_t) 2048;
size = (size + (off_t) 0x7fff) & ~((off_t) 0x7fff);
* (off_t) 2048;
if (size % o->obs)
size += (off_t) (o->obs - (size % o->obs));
ret = d->reserve_track(d, size);
if (ret <= 0) {
sprintf(msg, "Cannot reserve track of %.f bytes",
@ -1105,10 +1161,11 @@ int burn_disc_open_track_dvd_plus_r(struct burn_write_opts *o,
if (o->write_type == BURN_WRITE_SAO &&
! burn_track_is_open_ended(s->track[tnum])) {
/* Round track size up to 32 KiB and reserve track */
/* Round track size up to write chunk size and reserve track */
size = ((off_t) burn_track_get_sectors(s->track[tnum]))
* (off_t) 2048;
size = (size + (off_t) 0x7fff) & ~((off_t) 0x7fff);
* (off_t) 2048;
if (size % o->obs)
size += (off_t) (o->obs - (size % o->obs));
ret = d->reserve_track(d, size);
if (ret <= 0) {
sprintf(msg, "Cannot reserve track of %.f bytes",
@ -1153,19 +1210,29 @@ int burn_disc_close_track_dvd_minus_r(struct burn_write_opts *o,
int burn_disc_finalize_dvd_plus_r(struct burn_write_opts *o)
{
struct burn_drive *d = o->drive;
char msg[80];
sprintf(msg, "Finalizing %s ...",
d->current_profile_text);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
"Finalizing DVD+R ...", 0, 0);
msg, 0, 0);
/* CLOSE SESSION, 101b, Finalize with minimal radius */
d->close_track_session(d, 2, 1); /* (2<<1)|1 = 5 */
if(d->current_profile == 0x41) { /* BD-R */
/* CLOSE SESSION, 110b, Finalize Disc */
d->close_track_session(d, 3, 0); /* (3<<1)|0 = 6 */
} else {
/* CLOSE SESSION, 101b, Finalize with minimal radius */
d->close_track_session(d, 2, 1); /* (2<<1)|1 = 5 */
}
sprintf(msg, "... finalizing %s done ",
d->current_profile_text);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
"... finalizing DVD+R done ", 0, 0);
msg, 0, 0);
return 1;
}
@ -1200,7 +1267,133 @@ int burn_disc_close_track_dvd_plus_r(struct burn_write_opts *o,
}
/* ts A61218 - A70129 */
/* <<<
#define Libburn_simplified_dvd_chunk_transactioN 1
*/
#ifdef Libburn_simplified_dvd_chunk_transactioN
/* ts A91114 : EXPERIMENTAL, NOT COMPLETELY IMPLEMENTED
Simplified data transmission for DVD. libburn via GNU/Linux USB is 30 %
slower than growisofs or cdrecord when transmitting 32 KB chunks.
With 64 KB chunks it is 20% faster than the competitors.
No heavy CPU load is visible but there might be subtle race conditions in
the USB driver which work better with shorter time gaps between WRITE
commands.
Insight: It is actually about the interference of track source reading
with SCSI writing via USB. growisofs reads with O_DIRECT into a
mmap()ed buffer. When doing the same, libburn with 32 KB chunks
reaches similar write speed.
On the other hand, 64 KB chunks are 20% faster than that and
are not improved by reading O_DIRECT.
O_DIRECT is a property of the input fd of struct burn_source.
It can only be done with properly aligned memory and with aligned
read size. Alignment size is file system system specific.
System call
mmap(NULL, (size_t) buffer_size, PROT_READ | PROT_WRITE,
MAP_SHARED | MAP_ANONYMOUS, -1, (off_t) 0);
is supposed to allocate a properly aligned buffer.
64 KB is supposed to be a safe size.
Actually mmap() seems to be the main cause for a positive effect
of O_DIRECT.
This simplified transmission function did not bring visible benefit.
So for now it is not worth to teach it all applicable details of old
CD sector oriented transmission.
@return 1= ok, go on , 2= no input with track->open_ended = nothing written
<= 0 = error
*/
static int transact_dvd_chunk(struct burn_write_opts *opts,
struct burn_track *track)
{
int curr = 0, valid, err;
struct burn_drive *d = opts->drive;
struct buffer *out = d->buffer;
unsigned char *data = out->data;
#ifdef Libburn_log_in_and_out_streaM
/* ts A61031 */
static int tee_fd= -1;
if(tee_fd==-1)
tee_fd= open("/tmp/libburn_sg_readin",
O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR);
#endif /* Libburn_log_in_and_out_streaM */
/* Read a chunk full of data */
/* ??? Do we have offset padding ? >>> First produce offset padding */;
/* <<<< */
if (0 && !track->eos) {
for (curr = 0; curr < opts->obs; curr += 2048) {
if (track->source->read != NULL)
valid = track->source->read(track->source,
data + curr, 2048);
else
valid = track->source->read_xt(track->source,
data + curr, 2048);
if (valid <= 0) {
track->eos = 1;
break;
}
track->sourcecount += valid;
#ifdef Libburn_log_in_and_out_streaM
if(tee_fd!=-1 && valid>0) {
write(tee_fd, data + curr, valid);
}
#endif /* Libburn_log_in_and_out_streaM */
}
} else if (!track->eos){
valid = track->source->read(track->source, data, opts->obs);
if (valid <= 0) {
track->eos = 1;
} else {
track->sourcecount += valid;
curr = valid;
#ifdef Libburn_log_in_and_out_streaM
if(tee_fd!=-1 && valid>0) {
write(tee_fd, data, valid);
}
#endif /* Libburn_log_in_and_out_streaM */
}
}
if (curr == 0 && track->open_ended) {
/* >>> allow tail padding */;
return 2;
}
if (curr < opts->obs)
memset(data + curr , 0, opts->obs - curr);
/* Write chunk */
out->bytes = opts->obs;
out->sectors = out->bytes / 2048;
err = d->write(d, d->nwa, out);
if (err == BE_CANCELLED)
return 0;
track->writecount += out->bytes;
track->written_sectors += out->sectors;
d->progress.buffered_bytes += out->bytes;
d->nwa += out->sectors;
out->bytes = 0;
out->sectors = 0;
return 1;
}
#endif /* Libburn_simplified_dvd_chunk_transactioN */
/* ts A61218 - A81208 */
int burn_dvd_write_track(struct burn_write_opts *o,
struct burn_session *s, int tnum, int is_last_track)
{
@ -1209,6 +1402,7 @@ int burn_dvd_write_track(struct burn_write_opts *o,
struct buffer *out = d->buffer;
int sectors;
int i, open_ended = 0, ret= 0, is_flushed = 0;
int first_buf_cap = 0, further_cap = 0, buf_cap_step = 1024;
/* ts A70213 : eventually expand size of track to max */
burn_track_apply_fillup(t, d->media_capacity_remaining, 0);
@ -1219,11 +1413,21 @@ int burn_dvd_write_track(struct burn_write_opts *o,
ret = burn_disc_open_track_dvd_minus_r(o, s, tnum);
if (ret <= 0)
goto ex;
/* Pioneer DVR-216D rev 1.09 hates multiple buffer inquiries
before the drive buffer is full.
*/
first_buf_cap = 0;
further_cap = -1;
} else if (d->current_profile == 0x1b || d->current_profile == 0x2b) {
/* DVD+R , DVD+R/DL */
ret = burn_disc_open_track_dvd_plus_r(o, s, tnum);
if (ret <= 0)
goto ex;
} else if (d->current_profile == 0x41) {
/* BD-R SRM */
ret = burn_disc_open_track_dvd_plus_r(o, s, tnum);
if (ret <= 0)
goto ex;
}
sectors = burn_track_get_sectors(t);
@ -1249,12 +1453,30 @@ int burn_dvd_write_track(struct burn_write_opts *o,
for (i = 0; open_ended || i < sectors; i++) {
/* From time to time inquire drive buffer */
if ((i%256)==0)
/* ts A91110: Eventually avoid to do this more than once
before the drive buffer is full. See above DVD-
*/
if (i == first_buf_cap ||
((i % buf_cap_step) == 0 &&
(i >= further_cap || further_cap < 0))) {
d->read_buffer_capacity(d);
if (further_cap < 0)
further_cap =
d->progress.buffer_capacity / 2048 + 128;
}
#ifdef Libburn_simplified_dvd_chunk_transactioN
ret = transact_dvd_chunk(o, t);
if (ret <= 0)
{ret = 0; goto ex;}
i += o->obs / 2048 - 1;
d->progress.sector += o->obs / 2048 - 1;
#else
/* transact a (CD sized) sector */
if (!sector_data(o, t, 0))
{ ret = 0; goto ex; }
#endif
if (open_ended) {
d->progress.sectors = sectors = i;
@ -1292,6 +1514,12 @@ int burn_dvd_write_track(struct burn_write_opts *o,
is_last_track);
if (ret <= 0)
goto ex;
} else if (d->current_profile == 0x41) {
/* BD-R SRM */
ret = burn_disc_close_track_dvd_plus_r(o, s, tnum,
is_last_track);
if (ret <= 0)
goto ex;
}
ret = 1;
ex:;
@ -1372,10 +1600,70 @@ int burn_disc_close_session_dvd_minus_r(struct burn_write_opts *o,
int burn_dvd_write_session(struct burn_write_opts *o,
struct burn_session *s, int is_last_session)
{
int i,ret;
int i, ret, multi_mem;
struct burn_drive *d = o->drive;
/* >>> open_session ? */
/* ts A90108 */
if (d->current_profile == 0x41 && d->status == BURN_DISC_APPENDABLE &&
d->state_of_last_session == 1) {
/* last session on BD-R is still open */;
/* BR-R were not closed by libburn-0.6.0.pl00 if o->multi==0.
This leads to an unreadable, but recoverable) media state.
Technically they are appendable although the last session
is not readable.
By default the open session gets closed here before the new
session is written. E.g. after writing a small dummy seesion
number 2 one can read session 1 and write session 3 which
points to data of session 1.
For the case that no media with 3 sessions is desired it is
possible to activate the following coarse single-session
closing code:
No new session will be written but calling programs will
report success. Quite misleading.
Activate only if really needed by
# define Libburn_bug_A90108_close_disC yes
*/
#ifdef Libburn_bug_A90108_close_disC
/* Close open session and media.
That was the goal of the failed run which led to the
unreadable (but recoverable) media state.
It is not easy to implement a general close function for
all media types. Therefore this pseudo write code is under
control of #ifdef.
*/
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020171,
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
"Closing BD-R with accidently open session",
0, 0);
d->close_track_session(d, 3, 0); /* CLOSE SESSION, 110b */
d->state_of_last_session = 3; /* mark as complete session */
d->status = BURN_DISC_FULL;
sleep(3); /* The caller might need time to arrange itself */
return 1;
#else /* Libburn_bug_A90108_close_disC */
/* This is the default mode.
*/
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020170,
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
"Closing open session before writing new one",
0, 0);
d->close_track_session(d, 1, 0); /* CLOSE SESSION, 010b */
d->state_of_last_session = 3; /* mark as complete session */
#endif /* ! Libburn_bug_A90108_close_disC */
}
for (i = 0; i < s->tracks; i++) {
ret = burn_dvd_write_track(o, s, i,
@ -1386,7 +1674,11 @@ int burn_dvd_write_session(struct burn_write_opts *o,
if (d->current_profile == 0x11 || d->current_profile == 0x14 ||
d->current_profile == 0x15) {
/* DVD-R , DVD-RW Sequential, DVD-R/DL Sequential */
multi_mem = o->multi;
if (!is_last_session)
o->multi = 1;
ret = burn_disc_close_session_dvd_minus_r(o, s);
o->multi = multi_mem;
if (ret <= 0)
return 0;
} else if (d->current_profile == 0x12 || d->current_profile == 0x43) {
@ -1408,6 +1700,8 @@ int burn_dvd_write_session(struct burn_write_opts *o,
}
} else if (d->current_profile == 0x1b || d->current_profile == 0x2b) {
/* DVD+R , DVD+R/DL do each track as an own session */;
} else if (d->current_profile == 0x41) {
/* BD-R SRM do each track as an own session */;
}
return 1;
}
@ -1611,8 +1905,12 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
/* ??? padding needed ??? cowardly doing it for now */
o->obs_pad = 1; /* fill-up track's last 32k buffer */
} else if (d->current_profile == 0x1b || d->current_profile == 0x2b) {
/* DVD+R , DVD+R/DL */
} else if (d->current_profile == 0x1b || d->current_profile == 0x2b ||
d->current_profile == 0x41) {
/* DVD+R , DVD+R/DL , BD-R SRM */
/* >>> ts A81208 : with BD-R set o->obs to 64 kB ? */
t = disc->session[0]->track[0];
o_end = ( burn_track_is_open_ended(t) && !o->fill_up_media );
default_size = burn_track_get_default_size(t);
@ -1627,8 +1925,8 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
}
ret = burn_disc_setup_dvd_plus_r(o, disc);
if (ret <= 0) {
sprintf(msg,
"Write preparation setup failed for DVD+R");
sprintf(msg, "Write preparation setup failed for %s",
d->current_profile == 0x41 ? "BD-R" : "DVD+R");
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020121,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
@ -1637,6 +1935,46 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
}
/* ??? padding needed ??? cowardly doing it for now */
o->obs_pad = 1; /* fill-up track's last 32k buffer */
if (d->do_stream_recording) {
if (d->current_profile == 0x41) /* BD-R */
o->obs = Libburn_bd_re_streamed_obS;
}
}
#ifdef Libburn_dvd_obs_default_64K
o->obs = 64 * 1024;
#endif
/* <<< test only : Does this increase effective speed with USB ?
ts A90801 : 64kB: speed with 16x DVD-R is 12 rather than 8
128kB: glibc complains about double free
With BURN_OS_TRANSPORT_BUFFER_SIZE
enlarged to 128 MB, the first WRITE fails
with an i/o error.
o->obs = 64 * 1024;
*/
if (o->dvd_obs_override >= 32 * 1024)
o->obs = o->dvd_obs_override;
if (o->obs > BUFFER_SIZE) {
sprintf(msg, "Chosen write chunk size %d exceeds system dependent buffer size", o->obs);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00000002, LIBDAX_MSGS_SEV_DEBUG,
LIBDAX_MSGS_PRIO_ZERO, msg, 0, 0);
o->obs = 32 * 1024; /* This size is required to work */
}
if (d->do_stream_recording &&
(d->current_profile == 0x43 || d->current_profile == 0x41) &&
o->obs < Libburn_bd_re_streamed_obS) {
/* LG GGW-H20 writes junk with stream recording and obs=32k */
sprintf(msg,
"Stream recording disabled because of small OS buffer");
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020176, LIBDAX_MSGS_SEV_NOTE,
LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
d->do_stream_recording = 0;
}
sprintf(msg, "dvd/bd Profile= %2.2Xh , obs= %d , obs_pad= %d",
@ -1668,7 +2006,7 @@ ex:;
burn_drive_mark_unready(d);
burn_drive_inquire_media(d);
d->busy = BURN_DRIVE_IDLE;
/* <<< d->busy = BURN_DRIVE_IDLE; */
return ret;
early_failure:;
return 0;
@ -1748,6 +2086,13 @@ int burn_stdio_read_source(struct burn_source *source, char *buf, int bufsize,
int burn_stdio_write(int fd, char *buf, int count, struct burn_drive *d,
int flag)
{
if (d->cancel)
return 0;
/*
fprintf(stderr, "libburn_DEBUG: write(%d, %lX, %d)\n",
fd, (unsigned long) buf, count);
*/
if (write(fd, buf, count) != count) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020148,
@ -1918,13 +2263,15 @@ int burn_stdio_write_track(struct burn_write_opts *o, struct burn_session *s,
break;
}
d->progress.sector++;
/* Flush to disk after each full MB */
if (d->progress.sector - prev_sync_sector >= 512) {
/* Flush to disk from time to time */
if (d->progress.sector - prev_sync_sector >=
o->stdio_fsync_size && o->stdio_fsync_size > 0) {
prev_sync_sector = d->progress.sector;
if (!o->simulate)
burn_stdio_sync_cache(d->stdio_fd, d, 1);
burn_stdio_slowdown(d, &prev_time, 512 * 2, 0);
}
if ((d->progress.sector % 512) == 0)
burn_stdio_slowdown(d, &prev_time, 512 * 2, 0);
}
/* Pad up buffer to next full o->obs (usually 32 kB) */
@ -1987,7 +2334,7 @@ ex:;
/* update media state records */
burn_drive_mark_unready(d);
d->busy = BURN_DRIVE_IDLE;
/* <<< d->busy = BURN_DRIVE_IDLE; */
return ret;
}
@ -1996,12 +2343,13 @@ void burn_disc_write_sync(struct burn_write_opts *o, struct burn_disc *disc)
{
struct cue_sheet *sheet;
struct burn_drive *d = o->drive;
struct buffer buf;
struct buffer *buffer_mem = o->drive->buffer;
struct burn_track *lt, *t;
int first = 1, i, ret, lba, nwa = 0;
int first = 1, i, ret, lba, nwa = 0, multi_mem;
off_t default_size;
char msg[80];
/* ts A60924 : libburn/message.c gets obsoleted
burn_message_clear_queue();
*/
@ -2009,11 +2357,41 @@ void burn_disc_write_sync(struct burn_write_opts *o, struct burn_disc *disc)
/* ts A61224 */
burn_disc_init_write_status(o, disc); /* must be done very early */
/* ts A80412 */
d->do_stream_recording = o->do_stream_recording;
/* ts A80412 , A90227 */
d->do_stream_recording = !!o->do_stream_recording;
if (o->do_stream_recording >= 16)
d->stream_recording_start = o->do_stream_recording;
else
d->stream_recording_start = 0;
/* ts A91122 : Get buffer suitable for sources made by
burn_os_open_track_src() */
d->buffer = burn_os_alloc_buffer(sizeof(struct buffer), 0);
if (d->buffer == NULL)
goto fail_wo_sync;
/* >>> ts A90321
d->buffer = &buf;
memset(d->buffer, 0, sizeof(struct buffer));
fprintf(stderr, "libburn_DEBUG: d->buffer = %lX , size = %d\n",
(unsigned long) d->buffer, (int) sizeof(struct buffer));
calloc() seems not to have the desired effect. valgrind warns:
==18251== Syscall param write(buf) points to uninitialised byte(s)
==18251== at 0x5071DEB: (within /lib64/libpthread-2.5.so)
==18251== by 0x4723FA: burn_stdio_write (write.c:1850)
==18251== by 0x4725DC: burn_stdio_mmc_write (write.c:1894)
==18251== by 0x483B7A: get_sector (sector.c:229)
==18251== by 0x484F11: sector_data (sector.c:639)
==18251== by 0x4729FE: burn_stdio_write_track (write.c:2012)
==18251== by 0x472CF4: burn_stdio_write_sync (write.c:2072)
==18251== by 0x472E8D: burn_disc_write_sync (write.c:2125) <<< we are here
==18251== by 0x460254: write_disc_worker_func (async.c:514)
==18251== by 0x506B09D: start_thread (in /lib64/libpthread-2.5.so)
==18251== by 0x55484CC: clone (in /lib64/libc-2.5.so)
*/
d->rlba = -150;
d->toc_temp = 9;
@ -2032,7 +2410,7 @@ void burn_disc_write_sync(struct burn_write_opts *o, struct burn_disc *disc)
goto ex;
}
/* ts A70521 : Linux 2.4 USB audio fails with 64 kiB */
/* ts A70521 : GNU/Linux 2.4 USB audio fails with 64 kiB */
/* ts A80414 : might need 64 kiB for BD-RE streaming */
/* buffer flush trigger for sector.c:get_sector() */
o->obs = Libburn_cd_obS;
@ -2148,7 +2526,12 @@ return crap. so we send the command, then ignore the result.
d->alba += 4500;
}
}
if (!burn_write_session(o, disc->session[i]))
multi_mem = o->multi;
if(i < disc->sessions - 1)
o->multi = 1;
ret = burn_write_session(o, disc->session[i]);
o->multi = multi_mem;
if (!ret)
goto fail;
lt = disc->session[i]->track[disc->session[i]->tracks - 1];
@ -2188,7 +2571,7 @@ return crap. so we send the command, then ignore the result.
burn_drive_inquire_media(d);
burn_print(1, "done\n");
d->busy = BURN_DRIVE_IDLE;
/* <<< d->busy = BURN_DRIVE_IDLE; */
/* ts A61012 : This return was traditionally missing. I suspect this
to have caused Cdrskin_eject() failures */
@ -2203,9 +2586,13 @@ fail_wo_sync:;
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Burn run failed", 0, 0);
d->cancel = 1;
d->busy = BURN_DRIVE_IDLE;
/* <<< d->busy = BURN_DRIVE_IDLE; */
ex:;
d->do_stream_recording = 0;
if (d->buffer != NULL)
burn_os_free_buffer((char *) d->buffer,
sizeof(struct buffer), 0);
d->buffer = buffer_mem;
return;
}
@ -2215,7 +2602,7 @@ int burn_random_access_write(struct burn_drive *d, off_t byte_address,
{
int alignment = 0, start, upto, chunksize, err, fd = -1, ret;
char msg[81], *rpt;
struct buffer buf;
struct buffer buf, *buffer_mem = d->buffer;
if (d->released) {
libdax_msgs_submit(libdax_messenger,
@ -2326,7 +2713,7 @@ int burn_random_access_write(struct burn_drive *d, off_t byte_address,
if(fd >= 0)
close(fd);
d->buffer = NULL;
d->buffer = buffer_mem;
d->busy = BURN_DRIVE_IDLE;
return 1;
}

View File

@ -1,5 +1,11 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later.
*/
#ifndef BURN__WRITE_H
#define BURN__WRITE_H

View File

@ -1,16 +1,16 @@
/* test/libburner.c , API illustration of burning data or audio tracks to CD */
/* Copyright (C) 2005 - 2007 Thomas Schmitt <scdbackup@gmx.net> */
/* Provided under GPLv2,see also "License and copyright aspects" at file end */
/* Copyright (C) 2005 - 2010 Thomas Schmitt <scdbackup@gmx.net> */
/* Provided under GPL, see also "License and copyright aspects" at file end */
/** Overview
libburner is a minimal demo application for the library libburn as provided
on http://libburnia-project.org . It can list the available devices, can
blank a CD-RW or DVD-RW, can format DVD-RW and BD-RE, can burn to CD-R,
CD-RW, DVD-R, DVD+R, DVD+R/DL, DVD+RW, DVD-RW, DVD-RAM, BD-RE.
Not supported yet: DVD-R/DL, BD-R.
blank a CD-RW or DVD-RW, can format DVD-RW and BD, can burn to CD-R,
CD-RW, DVD-R, DVD+R, DVD+R/DL, DVD+RW, DVD-RW, DVD-RAM, BD-R, BD-RE.
Not supported yet: DVD-R/DL.
It's main purpose, nevertheless, is to show you how to use libburn and also
to serve the libburnia team as reference application. libburner.c does indeed
@ -26,19 +26,35 @@
approaches are shown here in application functions:
libburner_aquire_by_adr() demonstrates usage as of cdrecord traditions
libburner_aquire_by_driveno() demonstrates a scan-and-choose approach
With that aquired drive you can blank a CD-RW
With that aquired drive you can blank a CD-RW or DVD-RW
libburner_blank_disc()
or you can format a DVD-RW to profile "Restricted Overwrite" (needed once)
or an unused BD-RE to default size
libburner_format_owrt()
With the aquired drive you can burn to CD or DVD
or an unused BD to default size with spare blocks
libburner_format()
With the aquired drive you can burn to CD, DVD, BD
libburner_payload()
When everything is done, main() releases the drive and shuts down libburn:
burn_drive_release();
burn_finish()
FreeBSD does not work well with the convenient synchronous signal handler. So
the waiting loops for blanking, formatting, and writing use the asynchronous
mode of the libburn signal handler. It will not shutdown the library and
abort the program, but rather tell the ongoing drive operation to stop as
soon as possible. After the loops and at the end of the program there is a
call to determine whether an abort happened:
burn_is_aborting()
Applications must use 64 bit off_t. E.g. by defining
#define _LARGEFILE_SOURCE
#define _FILE_OFFSET_BITS 64
or take special precautions to interface with the library by 64 bit integers
where libburn/libburn.h prescribes off_t.
This program gets fed with appropriate settings externally by libburn's
autotools generated build system.
*/
/** See this for the decisive API specs . libburn.h is The Original */
/* For using the installed header file : #include <libburn/libburn.h> */
/* This program insists in the own headerfile. */
@ -106,7 +122,7 @@ int libburner_aquire_drive(char *drive_adr, int *driveno)
ret = libburner_aquire_by_adr(drive_adr);
else
ret = libburner_aquire_by_driveno(driveno);
if (ret <= 0)
if (ret <= 0 || *driveno <= 0)
return ret;
burn_disc_get_profile(drive_list[0].drive, &current_profile,
current_profile_name);
@ -260,7 +276,8 @@ int libburner_aquire_by_driveno(int *driveno)
}
/** Makes a previously used CD-RW ready for thorough re-usal.
/** Makes a previously used CD-RW or unformatted DVD-RW ready for thorough
re-usal.
To our knowledge it is hardly possible to abort an ongoing blank operation
because after start it is entirely handled by the drive.
@ -299,9 +316,12 @@ int libburner_blank_disc(struct burn_drive *drive, int blank_fast)
"FATAL : Media is not of erasable type\n");
return 0;
}
printf(
"Beginning to %s-blank media.\n", (blank_fast?"fast":"full"));
/* Switch to asynchronous signal handling for the time of waiting */
burn_set_signal_handling("libburner : ", NULL, 0x30);
printf("Beginning to %s-blank media.\n", (blank_fast?"fast":"full"));
burn_disc_erase(drive, blank_fast);
sleep(1);
while (burn_drive_get_status(drive, &p) != BURN_DRIVE_IDLE) {
if(p.sectors>0 && p.sector>=0) /* display 1 to 99 percent */
@ -310,6 +330,10 @@ int libburner_blank_disc(struct burn_drive *drive, int blank_fast)
printf("Blanking ( %.1f%% done )\n", percent);
sleep(1);
}
if (burn_is_aborting(0) > 0)
return -1;
/* Back to synchronous handling */
burn_set_signal_handling("libburner : ", NULL, 0);
printf("Done\n");
return 1;
}
@ -322,24 +346,35 @@ int libburner_blank_disc(struct burn_drive *drive, int blank_fast)
Formats unformatted BD-RE to default size. This will allocate some
reserve space, test for bad blocks and make the media ready for writing.
Expect a very long run time.
Formats unformatted blank BD-R to hold a default amount of spare blocks
for eventual mishaps during writing. If BD-R get written without being
formatted, then they get no such reserve and will burn at full speed.
*/
int libburner_format_owrt(struct burn_drive *drive)
int libburner_format(struct burn_drive *drive)
{
struct burn_progress p;
double percent = 1.0;
int ret, status, num_formats, format_flag= 0;
off_t size = 0;
unsigned dummy;
enum burn_disc_status disc_state;
if (current_profile == 0x13) {
fprintf(stderr, "IDLE: DVD-RW media is already formatted\n");
return 2;
} else if (current_profile == 0x43) {
} else if (current_profile == 0x41 || current_profile == 0x43) {
disc_state = burn_disc_get_status(drive);
if (disc_state != BURN_DISC_BLANK && current_profile == 0x41) {
fprintf(stderr,
"FATAL: BD-R is not blank. Cannot format.\n");
return 0;
}
ret = burn_disc_get_formats(drive, &status, &size, &dummy,
&num_formats);
if (ret > 0 && status == BURN_FORMAT_IS_FORMATTED) {
if (ret > 0 && status != BURN_FORMAT_IS_UNFORMATTED) {
fprintf(stderr,
"IDLE: BD-RE media is already formatted\n");
"IDLE: BD media is already formatted\n");
return 2;
}
size = 0; /* does not really matter */
@ -348,9 +383,10 @@ int libburner_format_owrt(struct burn_drive *drive)
size = 128 * 1024 * 1024;
format_flag = 1; /* write initial 128 MiB */
} else {
fprintf(stderr, "FATAL: Can only format DVD-RW or BD-RE\n");
fprintf(stderr, "FATAL: Can only format DVD-RW or BD\n");
return 0;
}
burn_set_signal_handling("libburner : ", NULL, 0x30);
printf("Beginning to format media.\n");
burn_disc_format(drive, size, format_flag);
@ -363,6 +399,9 @@ int libburner_format_owrt(struct burn_drive *drive)
printf("Formatting ( %.1f%% done )\n", percent);
sleep(1);
}
if (burn_is_aborting(0) > 0)
return -1;
burn_set_signal_handling("libburner : ", NULL, 0);
burn_disc_get_profile(drive_list[0].drive, &current_profile,
current_profile_name);
if (current_profile == 0x14 || current_profile == 0x13)
@ -476,7 +515,7 @@ int libburner_payload(struct burn_drive *drive,
/* Give up local reference to the data burn_source object */
burn_source_free(data_src);
} /* trackno loop end */
} /* trackno loop end */
/* Evaluate drive and media */
disc_state = burn_disc_get_status(drive);
@ -508,6 +547,7 @@ int libburner_payload(struct burn_drive *drive,
fprintf(stderr, "Reasons given:\n%s\n", reasons);
return 0;
}
burn_set_signal_handling("libburner : ", NULL, 0x30);
printf("Burning starts. With e.g. 4x media expect up to a minute of zero progress.\n");
start_time = time(0);
@ -555,6 +595,8 @@ int libburner_payload(struct burn_drive *drive,
}
burn_session_free(session);
burn_disc_free(target_disc);
if (burn_is_aborting(0) > 0)
return -1;
if (multi && current_profile != 0x1a && current_profile != 0x13 &&
current_profile != 0x12 && current_profile != 0x43)
/* not with DVD+RW, formatted DVD-RW, DVD-RAM, BD-RE */
@ -614,7 +656,8 @@ int libburner_setup(int argc, char **argv)
}
strcpy(drive_adr, argv[i]);
}
} else if (!strcmp(argv[i], "--format_overwrite")) {
} else if ((!strcmp(argv[i], "--format_overwrite")) ||
(!strcmp(argv[i], "--format"))) {
do_blank = 101;
} else if (!strcmp(argv[i], "--multi")) {
@ -655,8 +698,7 @@ int libburner_setup(int argc, char **argv)
if (print_help || insuffient_parameters ) {
printf("Usage: %s\n", argv[0]);
printf(" [--drive <address>|<driveno>|\"-\"] [--audio]\n");
printf(" [--blank_fast|--blank_full|--format_overwrite]\n");
printf(" [--try_to_simulate]\n");
printf(" [--blank_fast|--blank_full|--format] [--try_to_simulate]\n");
printf(" [--multi] [<one or more imagefiles>|\"-\"]\n");
printf("Examples\n");
printf("A bus scan (needs rw-permissions to see a drive):\n");
@ -669,8 +711,8 @@ int libburner_setup(int argc, char **argv)
printf(" %s --drive /dev/hdc --blank_fast\n",argv[0]);
printf("Blank a used DVD-RW (is combinable with burning in one run):\n");
printf(" %s --drive /dev/hdc --blank_full\n",argv[0]);
printf("Format a DVD-RW to avoid need for blanking before re-use:\n");
printf(" %s --drive /dev/hdc --format_overwrite\n", argv[0]);
printf("Format a DVD-RW, BD-RE or BD-R:\n");
printf(" %s --drive /dev/hdc --format\n", argv[0]);
printf("Burn two audio tracks (to CD only):\n");
printf(" lame --decode -t /path/to/track1.mp3 track1.cd\n");
printf(" test/dewav /path/to/track2.wav -o track2.cd\n");
@ -690,6 +732,13 @@ int main(int argc, char **argv)
{
int ret;
/* A warning to programmers who start their own projekt from here. */
if (sizeof(off_t) != 8) {
fprintf(stderr,
"\nFATAL: Compile time misconfiguration. off_t is not 64 bit.\n\n");
exit(39);
}
ret = libburner_setup(argc, argv);
if (ret)
exit(ret);
@ -706,7 +755,7 @@ int main(int argc, char **argv)
/* Print messages of severity SORRY or more directly to stderr */
burn_msgs_set_severities("NEVER", "SORRY", "libburner : ");
/* Activate the default signal handler which eventually will try to
/* Activate the synchronous signal handler which eventually will try to
properly shutdown drive and library on aborting events. */
burn_set_signal_handling("libburner : ", NULL, 0);
@ -720,7 +769,7 @@ int main(int argc, char **argv)
{ ret = 0; goto release_drive; }
if (do_blank) {
if (do_blank > 100)
ret = libburner_format_owrt(drive_list[driveno].drive);
ret = libburner_format(drive_list[driveno].drive);
else
ret = libburner_blank_disc(drive_list[driveno].drive,
do_blank == 1);
@ -740,10 +789,14 @@ release_drive:;
burn_drive_release(drive_list[driveno].drive, 0);
finish_libburn:;
if (burn_is_aborting(0) > 0) {
burn_abort(4400, burn_abort_pacifier, "libburner : ");
fprintf(stderr,"\nlibburner run aborted\n");
exit(1);
}
/* This app does not bother to know about exact scan state.
Better to accept a memory leak here. We are done anyway. */
/* burn_drive_info_free(drive_list); */
burn_finish();
exit(ret);
}
@ -756,37 +809,6 @@ Read. Try. Think. Play. Write yourself some code. Be free of my copyright.
Be also invited to study the code of cdrskin/cdrskin.c et al.
Clarification in my name and in the name of Mario Danic, copyright holder
on toplevel of libburnia. To be fully in effect after the remaining other
copyrighted code has been replaced by ours and by copyright-free contributions
of our friends:
We, the copyright holders, agree on the interpretation that
dynamical linking of our libraries constitutes "use of" and
not "derivation from" our work in the sense of GPL, provided
those libraries are compiled from our unaltered code.
Thus you may link our libraries dynamically with applications
which are not under GPL. You may distribute our libraries and
application tools in binary form, if you fulfill the usual
condition of GPL to offer a copy of the source code -altered
or unaltered- under GPL.
We ask you politely to use our work in open source spirit
and with the due reference to the entire open source community.
If there should really arise the case where above clarification
does not suffice to fulfill a clear and neat request in open source
spirit that would otherwise be declined for mere formal reasons,
only in that case we will duely consider to issue a special license
covering only that special case.
It is the open source idea of responsible freedom which will be
decisive and you will have to prove that you exhausted all own
means to qualify for GPL.
For now we are firmly committed to maintain one single license: GPL.
History:
libburner is a compilation of my own contributions to test/burniso.c and
fresh code which replaced the remaining parts under copyright of

View File

@ -1,7 +1,7 @@
/* test/telltoc.c , API illustration of obtaining media status info */
/* Copyright (C) 2006 - 2007 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 */
/* Copyright (C) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL */
/** Overview