Compare commits

...

842 Commits

Author SHA1 Message Date
ed7dd1e748 Bug fix: BD-R were not correctly finalized 2009-01-07 16:59:57 +00:00
cff7bc9291 Mentioned bug fix and pl01 2009-01-07 16:57:55 +00:00
9e26f4e5ae Branching for libburn bugfix release 0.6.0.pl01 2009-01-07 16:50:04 +00:00
c70742da56 libburn release 0.6.0 is ready 2009-01-04 11:59:50 +00:00
bd6874e7d1 Documented changes and release timestamp 2009-01-02 17:11:31 +00:00
65f67f7b5d Updated cdrskin tarball generator 2009-01-02 17:01:31 +00:00
6127790ab2 Made number transition to 0.6.0 2009-01-02 16:59:24 +00:00
a4ca88d5f8 Updated copyright claims to year 2009 2009-01-02 16:30:50 +00:00
e25bce8f12 Branching for libburn release 0.6.0 2009-01-02 16:18:58 +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
f64ed23a98 Reacted on harmless compiler warning 2008-08-19 12:36:10 +00:00
730c1555ab API clarification about CD burn_toc_entries 2008-08-19 12:26:48 +00:00
acd7dbc5c6 New flag bit2 with burn_read_data() 2008-08-09 07:19:54 +00:00
6dc9ecbcad CD burn_toc_entries now bear extension_valid data 2008-08-09 07:18:53 +00:00
5a99f9c4d8 Updated for next 0.5.1 cycle 2008-08-05 18:11:09 +00:00
ea17318e18 Taking into respect drive list from /proc/sys/dev/cdrom/info 2008-08-05 18:00:37 +00:00
98d742a4ef Avoiding drive scan if single drive is given 2008-08-01 10:10:13 +00:00
332a92ac78 Documented changes and release timestamp 2008-07-16 09:14:28 +00:00
6c50416d3c Updated cdrskin tarball generator 2008-07-16 09:13:36 +00:00
91d678a503 Made number transition to 0.5.1 and activated development documentation 2008-07-16 09:12:22 +00:00
76e85e600c Followed hint of Giulio Orsero to recognize disk by /proc/ide/hdX/media 2008-07-14 16:44:59 +00:00
9d48bb6892 New API call burn_fifo_peek_data() 2008-07-14 11:38:22 +00:00
38f0399fff Did LT_CURRENT++, LT_AGE++ because of new API call 2008-07-14 11:31:16 +00:00
39198ff8cb Making visible the new NOTE and HINT about busy alleged hard disks 2008-07-14 11:30:09 +00:00
67ca4a251a Trying to avoid SORRY messages when hitting busy hard disk /dev/hdX 2008-07-14 11:28:55 +00:00
b1c6953b61 With auto device family: scd is now fallback if sr does not exist 2008-07-02 09:39:02 +00:00
eb95d89272 Inserted @since tags for all functions older than 0.2.0 2008-06-14 14:06:38 +00:00
548051e53f Updated release history 2008-06-14 14:05:47 +00:00
a72b38c116 Documented changes and release timestamp 2008-05-17 12:09:02 +00:00
a67aa2ccee Updated cdrskin tarball generator 2008-05-17 12:06:38 +00:00
2fb5ea8def Made number transition to 0.4.9 2008-05-17 12:05:36 +00:00
55061cb7cf Made inability to get format list a reason to abort the program 2008-05-14 16:52:35 +00:00
4b3ec06cc4 Added format types 0x30 and 0x32 to list in API comments 2008-05-14 16:51:40 +00:00
ad6bd91b21 Bug fix: random access addressing for DVD-RAM and BD-RE did not work 2008-05-14 16:50:27 +00:00
0e2aaa2d59 Documented changes and release timestamp 2008-05-10 13:43:12 +00:00
4244a3c141 Updated cdrskin tarball generator 2008-05-10 13:41:58 +00:00
e4d30e4762 Made number transition to 0.4.7 2008-05-10 13:40:55 +00:00
2856e9c984 Changed blank examples to blank=as_needed 2008-05-09 19:42:49 +00:00
6660ef7ece Allowed BD-ROM and BD-R for read-only purposes 2008-05-09 14:51:48 +00:00
37092086d9 Documented read-only profiles CD-ROM and DVD-ROM 2008-05-09 14:31:12 +00:00
35d1394262 Declared BD-RE to be supported 2008-05-06 18:35:48 +00:00
4dec38984d Declared BD-RE to be supported 2008-05-06 18:17:05 +00:00
be0626ae9e Declared BD-RE to be supported 2008-05-06 18:10:44 +00:00
a54113267e Declared BD-RE to be supported 2008-05-06 18:08:04 +00:00
2d9d250471 Mapped undefined size to 0 with burn_disc_get_formats() and DVD-RW 2008-05-06 08:41:48 +00:00
ff7520f2f5 Avoided to report negative burn_multi_caps.start_range_high with DVD-RW 2008-05-06 08:24:11 +00:00
d0d90fc902 Updated project history 2008-05-03 11:16:12 +00:00
1d41767348 Documented newest enhancements 2008-04-27 16:36:13 +00:00
12b0fbf17c New blank type as_needed 2008-04-27 14:02:32 +00:00
44368aef6c New blank type format_if_needed 2008-04-27 08:47:55 +00:00
43b6ad6008 New blank subtypes format_defectmgt_cert_[on|off], on is default 2008-04-26 15:10:35 +00:00
f006ee5436 Enabled quick formatting with DVD-RAM, made slow formatting default with BD-RE 2008-04-26 15:07:39 +00:00
5e4da147a5 Documented newest enhancements 2008-04-25 13:44:01 +00:00
103b301b09 Incremented LT_CURRENT and LT_AGE to reflect API enhancements 2008-04-25 13:36:19 +00:00
0386feabfe Documented experimental support for BD-RE formatting 2008-04-25 13:24:39 +00:00
4e949d79fe Preparations for formatting BD-RE 2008-04-25 13:16:23 +00:00
422a97a2f2 Mentioned new features 2008-04-24 18:37:46 +00:00
a52ea438a5 Wrote down what was learned about DVD-RAM formatting 2008-04-24 18:37:02 +00:00
62f41452bb New blank type blank=format_by_index_<number> 2008-04-23 11:02:11 +00:00
015bc00a91 New option --list_formats 2008-04-22 20:10:38 +00:00
d6fde26824 Adjustments with DVD-RAM formatting 2008-04-22 16:13:05 +00:00
1cfb29f032 Adjustments with DVD-RAM formatting 2008-04-18 19:46:18 +00:00
65cf751a30 Began to implement formatting of DVD-RAM and experimentally of BD-RE 2008-04-18 09:28:16 +00:00
4683386de1 Began to implement formatting of DVD-RAM and experimentally of BD-RE 2008-04-18 09:27:16 +00:00
5d51869c3b Made burn_read_data() obey its flag bit1 2008-04-16 08:22:14 +00:00
fe8a6c6224 Some adjustments of cdrskin man page 2008-04-15 09:43:33 +00:00
db5568c03b Enforced tail padding with stream_recording, enlarged transport buffer 2008-04-15 09:42:32 +00:00
a07631c57b New option stream_recording=on|off 2008-04-12 16:46:05 +00:00
e522db6220 New API call burn_write_opts_set_stream_recording() 2008-04-12 16:42:45 +00:00
51ac900de6 Trying to fix bugs about BD-RE, macro for simulating BD-RE on DVD-RAM 2008-04-10 21:16:07 +00:00
cdea153443 Switched from configure.ac versioning to libburn.h versioning 2008-04-08 13:35:43 +00:00
0ce3f7c224 Updated cdrskin tarball generator 2008-04-08 13:34:14 +00:00
8de0a3dc6c Made number transition 2008-04-08 13:32:07 +00:00
e75e5e04b8 Corrected GPL version 2008-04-02 07:48:24 +00:00
86d5bdfef8 Got rid of a cumbersome open-close cycle with burn_read_data() on stdio: 2008-03-03 20:30:10 +00:00
c1298d82a6 Updated changelog 2008-03-01 18:48:32 +00:00
5c6366ecbd Mentioned support for DVD+R/DL. 2008-02-28 13:24:08 +00:00
616454c737 Made support for DVD+R DL official, enabled untested support for BD-RE 2008-02-28 12:32:34 +00:00
ea6957ef68 Changed meaning of unrecognized severity texts from FATAL to ALL 2008-02-22 21:38:09 +00:00
f9398c08e6 Imported changes from libiso_msgs.h 2008-02-22 21:36:08 +00:00
b4617c679c New error code 0x00040008 2008-02-22 15:10:21 +00:00
42bb74881a Weakened demand to print file path in following message 2008-02-21 21:53:26 +00:00
61671b41d7 Mapped unknown severity text to ALL rather than NEVER 2008-02-21 20:22:53 +00:00
1e74d7a04e Introduced severity ERRFILE 2008-02-21 20:14:23 +00:00
c48244abfc Directed error message to proper output channel 2008-02-21 20:11:20 +00:00
13492efe4b Testwise inquiry of ioctl(CDROM_MEDIA_CHANGED) (disabled by default) 2008-02-21 20:10:38 +00:00
bccb39efd8 Updated project interrelations 2008-02-16 12:37:09 +00:00
6fc60be93c Corrected typo in comment 2008-02-16 12:11:42 +00:00
d69b856b6a Pointed to ldconfig 2008-02-14 08:39:12 +00:00
b5e2d60c68 Updated year 2008-02-14 08:36:02 +00:00
ff1ad50119 Micro corrections in comment text 2008-02-14 07:41:51 +00:00
4cb6706307 Introduced LIBDAX_MSGS_SEV_MISHAP 2008-02-11 19:15:21 +00:00
6e74c8bc2e Allowed DVD +/- DL for reading 2008-02-08 07:34:58 +00:00
fdbed06f84 Added debug message in case of burn_read_data() return 0 2008-02-07 23:29:26 +00:00
67e4282b82 Installed a simple address logger in burn_read_data 2008-02-06 23:01:45 +00:00
bd8d4bb49f Copied usage discussion about *_header_version_* from libisoburn 2008-02-06 18:23:06 +00:00
623edf9d9d Re-instated range "vreixo" with old and new codes, adjusted severity definitions 2008-02-06 17:41:00 +00:00
d4fe8c75be Registered range "libisoburn" 0x00060000 to 0x00006ffff 2008-02-04 17:52:56 +00:00
9ebd020847 Announced deprecation of libisofs-0.2.x, temporory employment of libisofs-0.6.1 2008-02-04 17:52:06 +00:00
a93d18231a New API call burn_sev_to_text() 2008-02-03 09:25:58 +00:00
ec8b75217f Incremented LT_* to get libburn.so.4.8.0 (forgot to do 4.7.1 anyway) 2008-02-03 09:22:29 +00:00
99767afe1f Registered error code range "libisofs-xorriso" 2008-02-03 09:21:01 +00:00
024076ad54 Changed "libburn interface :" version message to libburn.h macros 2008-02-01 10:06:21 +00:00
c39e7d8ce4 Renamed libburn-5.pc to libburn-1.pc 2008-02-01 10:03:56 +00:00
95609061f1 Introduced compile time check of libburn header version 2008-01-31 11:11:50 +00:00
d498003515 Corrected description of major.minor.micro definition in libburn.h 2008-01-29 21:41:59 +00:00
b1630a3b33 Moving the major.minor.micro definition from configure.ac to libburn.h 2008-01-29 21:09:16 +00:00
eddf4e6b13 Updated cdrskin tarball generator 2008-01-27 15:18:12 +00:00
654e25d40a Made number transition to 0.4.3 , still libburn.so.4.7.0 2008-01-27 14:53:55 +00:00
69e1d4a51f Disabled debugging messages about thread properties 2008-01-26 18:03:36 +00:00
305917fe86 Made a sudden end to all stdio drives in burn_abort() 2008-01-26 13:16:12 +00:00
b3b42ff649 Ported change in vreixo message range from isoburn_msgs 2008-01-26 12:31:42 +00:00
63d1f5dcbf Adapted to man -H on my new system 2008-01-26 12:30:22 +00:00
77a9a1fc92 Dynamic cdrskin linking patch by Simon Huggins. 2008-01-23 21:37:26 +00:00
beb1c1d2d1 Implemented run time check of libburn version. 2008-01-23 21:18:25 +00:00
e449654c7b Introduced message severity "FAILURE" 2008-01-23 19:39:38 +00:00
d66a40bc0e Made burn_read_data() issue messages about hopeless drive access errors 2008-01-23 19:34:38 +00:00
bed900f3f4 Fixed small bug about error messages with burn_read_data 2008-01-19 20:18:13 +00:00
922fc6c90b Removed a reference to future GPL versions 2008-01-17 18:54:38 +00:00
adac21d6ee Changed meaning of .driveno to .origin, introduced LIBDAX_MSGS_ORIGIN_* macros 2008-01-17 18:51:46 +00:00
d9e056c3ac Implemented burn_source.cancel() in a binary backwards compatible way 2007-12-24 14:21:23 +00:00
32a6bd1f82 Some changes in the comments 2007-12-08 13:49:46 +00:00
9f7be91aba Made postponed change in thread management 2007-12-07 18:53:22 +00:00
fec4fd864f An attempt to rectify .so numbering: SONAME=10, REV=1, AGE=6 2007-12-07 18:51:57 +00:00
e48014caea Adjusted meaning of --read_and_print count= -1 2007-11-29 18:55:52 +00:00
82c6e92da0 Enabled reading of TOC from ROM drives (direly needed for xorriso) 2007-11-29 18:55:06 +00:00
206910da4e Reacted on build warnings on another system 2007-11-26 15:49:39 +00:00
0a27b188a3 Reacted on build warnings on a 64 Bit system 2007-11-18 09:36:41 +00:00
6705389f14 Corrected a typo in cdrskin man page 2007-11-18 09:35:36 +00:00
5c8d6865b5 Marked loss of binary backward compatibility back in rev 655, libburn-0.3.1 2007-11-18 09:34:33 +00:00
2d6d2679a0 Updated cdrskin release generator scripts 2007-10-29 16:47:49 +00:00
5432612965 Returned to -5 naming 2007-10-28 22:37:18 +00:00
9b1a57d84a Revekod changes to trunk 2007-10-28 22:36:09 +00:00
e5ea580e3b Fixed completely things wrt pc-in files 2007-10-28 19:15:52 +00:00
981a1bf5e1 Fixed build system wrt pc-in files 2007-10-28 19:14:21 +00:00
49925ad2ba Changed sonumber to 4, and changed pc.in file 2007-10-28 12:53:18 +00:00
fc5f2a4745 Reacted on cdwrite@ message about INT_MAX in cdrom.h of kernel 2.6.23 2007-10-27 07:52:54 +00:00
903a12c90b Added forgotten help text lines 2007-10-25 13:18:48 +00:00
0f50c21888 Updated cdrskin tarball generator 2007-10-25 09:37:06 +00:00
f3739013fa Made number transition to 0.4.1 2007-10-25 09:26:02 +00:00
bc5bb95dba Fixed a bug about arrays 2007-10-23 16:06:17 +00:00
cb68f7e0b7 Work goes on 2007-10-23 16:05:07 +00:00
63939c4f25 Preparations for lowercase class and function names 2007-10-23 16:00:14 +00:00
1280fdf221 Next cdrskin-0.3.9 cycle 2007-10-23 15:58:45 +00:00
3199bc21aa Removed useless alternative after zombies turned out to be caused by gdb 2007-10-19 13:32:49 +00:00
2d131a1741 Small change with debug verbosity of abort handler 2007-10-19 13:27:59 +00:00
cd84357589 Starting threads detached, providing two alternatives. But zombies still there. 2007-10-19 11:53:19 +00:00
e98a90cecf Prevented SIGSEGV with burn_msgs_obtain() on non-initialized library 2007-10-18 20:03:50 +00:00
2a669879a4 Calmed down hyperactive sleep interval with drive scanning 2007-10-18 19:39:13 +00:00
e6885f7fac New API function burn_text_to_sev() 2007-10-16 21:22:29 +00:00
191db530c5 Activated re-usal of disposed global drive_array slots 2007-10-15 14:41:29 +00:00
c3d9155340 Corrected SIGSEGV with changing from one drive to the other 2007-10-15 11:59:34 +00:00
3119ed2af3 Made possible to silence error message about missing pseudo drive 2007-10-15 11:58:08 +00:00
5eb47cd3ed Corrected 4-byte buffer overflow (which did no detectable harm) 2007-10-15 11:55:34 +00:00
6864b1d621 Minor changes with waiting for drive and fifo status display 2007-10-07 11:06:37 +00:00
5ad09b55ee Corrected status reply for unstarted fifo (2nd try) 2007-10-07 11:05:00 +00:00
f4fe30ec6c Corrected status reply for unstarted fifo 2007-10-07 11:03:07 +00:00
a63d9b11c4 Fixed data spoiling bug with ring buffer introduced with rev 1155 2007-10-05 23:15:25 +00:00
ee7fcf7522 Revoked urge to have a magic[4] in burn_source (free_data is magic enough) 2007-10-05 08:57:52 +00:00
ed53a67a2b Corrected abort preventing bug introduced with revision 1131 2007-10-04 21:29:49 +00:00
bc1944b970 Minor adjustments with comment text 2007-10-04 21:02:06 +00:00
e065ff1db7 Inserted the necessary error messages and magic numbers 2007-10-04 20:06:38 +00:00
e5f42759a0 Inserted the necessary error messages and magic numbers 2007-10-04 20:00:58 +00:00
f3966e5fee Made use of 4 MB fifo 2007-10-03 22:38:39 +00:00
e2479d6088 More documentation for burn_source, new API call burn_fifo_inquire_status() 2007-10-03 22:37:39 +00:00
291ef125b0 Implemented the ring buffer of burn_fifo_source_new() object 2007-10-03 22:35:37 +00:00
771e659a43 More documentation for burn_source 2007-10-03 11:54:42 +00:00
f71c2079ff Ensured synchronize cache before release 2007-10-03 11:24:41 +00:00
01ec5f031d More documentation for burn_source 2007-10-03 08:41:01 +00:00
ce7678b8f4 Corrected error with revision 1145 2007-10-02 17:59:12 +00:00
769ea039a1 Clarified role of burn_source 2007-10-02 13:54:54 +00:00
fc6163732e Moved minimum tracksize padding out of TAO track closing. Now done before sync. 2007-10-02 12:06:11 +00:00
1efbf27fe3 Disallowed --read_and_print raw:- , allowed to write to chardev+pipe+socket 2007-09-30 21:26:25 +00:00
214de7d7df Implemented a simple fifo to decouple from burn_source signals 2007-09-30 21:24:55 +00:00
97403bb20e Added forgotten handling of non-writer-non-control threads 2007-09-29 19:15:49 +00:00
5d93e04b28 Trying to catch signals from within the writer thread 2007-09-29 18:50:19 +00:00
3dda4b92b9 Next cdrskin-0.3.9 cycle 2007-09-27 10:39:37 +00:00
ec763a5ec9 Corrected announcement with dev=help about stdio: "Open via UNIX device" 2007-09-27 09:32:13 +00:00
06ec817caa Disallowed emulated drives for superuser, allowed stdio:/dev/null for all 2007-09-27 08:34:26 +00:00
ff9715aa78 Made -O2 default if not -g is given 2007-09-26 17:39:35 +00:00
7ec2972988 Streamlined and moved legal stuff to end of text 2007-09-26 16:00:32 +00:00
24d6db4b64 Disabled --allow_emulated_drives in setuid runs 2007-09-26 15:53:43 +00:00
011ba599cd Blocked against file descriptor drives. Too dangerous for a demo. 2007-09-24 18:21:32 +00:00
78c16e7590 Made stdio-drives work on readonly CD block devices 2007-09-24 18:14:07 +00:00
c78403d8cf Took into respect new drive role 3 2007-09-24 13:58:47 +00:00
5e995c9cd0 Implemented drive role 3, sequential write-only stdio drives (e.g. stdout) 2007-09-24 13:54:52 +00:00
83fe9f3621 Added forgotten handling of "sdtio:" with burn_drive_equals_adr() 2007-09-24 06:24:02 +00:00
9e4996a3b5 Updated a comment about Immed and a debug message with tray loading 2007-09-23 16:35:44 +00:00
0721cf89d1 Made use of burn_drive_equals_adr() 2007-09-23 16:34:34 +00:00
78dd75b1ff New API function burn_drive_equals_adr() 2007-09-23 16:33:21 +00:00
606c863a55 Reacted on compiler warning 2007-09-22 19:30:45 +00:00
282e228a6b New API function burn_msgs_submit() 2007-09-22 15:17:41 +00:00
d8990e820e Updated list of unsupported cdrecord and wodim options 2007-09-22 14:06:43 +00:00
af3c8aaa5d Had to revoke Immed bit on load command. LG GSA-4082B : premature "no media" 2007-09-21 12:04:27 +00:00
1e78652ac9 Triggered fallback by unsuitable media, made -version report fallback program 2007-09-20 13:00:02 +00:00
a6f41f8beb New option fallback_program= 2007-09-19 21:28:18 +00:00
9930c22d4a Made minor corrections 2007-09-19 14:18:48 +00:00
e71c12caf3 Made cdrskin/compile_cdrskin.sh -do_diet work again 2007-09-19 14:18:14 +00:00
5e9b8b6341 Next cdrskin-0.3.9 cycle 2007-09-19 12:46:53 +00:00
5230cb0c1d Did a little overhaul of general paragraphs, mentioned new option -waiti 2007-09-19 10:12:24 +00:00
85f24401a8 Implemented emulation for cdrecord option -waiti 2007-09-19 09:40:16 +00:00
190ad329fd Implemented emulation for cdrecord option -immed 2007-09-18 20:40:14 +00:00
c8e9249e9d Changed some comments, reacted on harmless compiler warning 2007-09-18 20:15:25 +00:00
e43ec2b295 Corrected an outdated HINT text 2007-09-18 20:04:22 +00:00
a80f8359fe Made use of Immed bit with 1Bh START STOP UNIT and 35h SYNCHRONIZE CACHE 2007-09-18 20:03:20 +00:00
129db7ee49 Made use of Immed bit with 5Bh CLOSE TRACK/SESSION 2007-09-18 13:03:24 +00:00
2748f396ae Implemented emulation for cdrecord option -lock 2007-09-18 09:06:26 +00:00
698866015e New API function burn_drive_leave_locked() 2007-09-18 09:05:05 +00:00
2b0ce8ec9a Learned helptexts for -inq, -format, -load from cdrecord (they are wrong, btw) 2007-09-18 07:20:23 +00:00
8fd2539a5c Implemented emulation for cdrecord options -inq , -format , -load 2007-09-17 16:35:33 +00:00
1077788276 Next cdrskin-0.3.9 cycle 2007-09-16 17:36:22 +00:00
361a110274 Equipped libdax_msgs with reference counter. Completed its mutex protection. 2007-09-15 20:41:25 +00:00
f379a2c91a New API function burn_set_messenger() 2007-09-15 17:19:45 +00:00
7654785d43 A sed converter which creates libiso_msgs.[ch] from libdax_msgs.[ch] 2007-09-15 17:18:05 +00:00
15b9f786c8 Prepared for neat sed translation. Explained concept of libdax_msgs variants. 2007-09-15 17:16:49 +00:00
635530b05e Imported Range "vreixo" into libburn/libdax_msgs.h 2007-09-15 11:21:27 +00:00
ab15717ce0 Documented burn_write_opts_set_multi @param opts 2007-09-14 12:24:19 +00:00
eb88f800d7 Took into respect time granularity with stdio speed control 2007-09-14 12:23:15 +00:00
1786e8008f Updated libisofs doxygen.conf.in 2007-09-14 09:03:06 +00:00
064ef80df9 Cleaned up authors file, move Lorenzo to contributors 2007-09-14 04:29:32 +00:00
488e970665 Fixed bug with direct_write_amount=0 2007-09-12 19:59:56 +00:00
02ede28b9e Implemented cache syncing for stdio-drives in burn_random_access_write() 2007-09-12 19:50:57 +00:00
e137f8fd20 Implemented realistic speed simulation with stdio-drives 2007-09-12 11:58:43 +00:00
854a806292 Reacted on compiler -O2 warnings 2007-09-12 11:57:49 +00:00
090861567d Brought burn_stdio_write_track() onto sector_data() for outmost realism 2007-09-12 10:45:34 +00:00
4b4f141fcc Added forgotten return 0 to an error case 2007-09-10 11:00:16 +00:00
c70a78c477 Ended falsely alleged erasability of DVD-RAM and DVD+RW 2007-09-09 18:28:05 +00:00
542afd7b3b Made use of os dependend stdio size estimation 2007-09-09 13:39:00 +00:00
75dd141055 Enable os dependend stdio size estimation 2007-09-09 13:31:29 +00:00
ffed552183 Fixed bug with dev=stdio: where path contains a digit 2007-09-09 09:36:36 +00:00
ea09a516bd Called statvfs() for size estimation of regular stdio-files. 2007-09-09 09:35:23 +00:00
ccad19e055 Next cdrskin-0.3.9 cycle 2007-09-08 17:50:48 +00:00
bdf862b429 Made Libburn_precheck_write_ruleS unconditional code 2007-09-08 17:47:59 +00:00
bdff3ac16c New option --allow_emulated_drives 2007-09-08 16:49:19 +00:00
2d3d255231 Documentation of stdio-drives 2007-09-08 16:09:52 +00:00
8bf8287c58 Changed speed measurement of stdio-drives to DVD 1x units 2007-09-08 13:22:10 +00:00
40cb77d953 Allowed -dummy burns with stdio-drives (because /dev/null is no block device) 2007-09-08 13:20:59 +00:00
df382b3f06 Made cdrskin work with null-drive (which it mistook for something like ATA:) 2007-09-08 10:26:15 +00:00
c8c349469d Fixed memory leak and possible SIGSEGV with pseudo-drives 2007-09-08 10:22:05 +00:00
1f7a6575bc Bug fix about stdio:<charcter device> 2007-09-07 23:47:07 +00:00
386149d5bf Report media profile in cdrskin blank, format, burn runs 2007-09-07 23:41:38 +00:00
c62e63a8d9 Made burn_drive_scan_and_grab() extend the drive list rather than replacing it 2007-09-07 19:09:25 +00:00
1935d222ed Lowered report severity to LIBDAX_MSGS_SEV_WARNING. 2007-09-07 18:47:51 +00:00
b812af96f7 Avoided locked tray after failed burn_finish() because of busy drive 2007-09-07 18:46:36 +00:00
5a8910cdd8 Forgotten file for revision 1006 2007-09-07 16:45:37 +00:00
0bbc34d861 Corrected memory leak introduced by revision 1005 2007-09-07 16:40:38 +00:00
8e171c89a6 Made burn_drive_scan() refuse work on non-empty drive list. 2007-09-07 15:50:31 +00:00
5283401fb0 Reacted on changed media profile of stdio-drives 2007-09-07 12:39:33 +00:00
0b13c31b07 Reacted on changed media profile of stdio-drives 2007-09-07 12:38:20 +00:00
e72b2fd732 Corrected write counter in burn_stdio_write_track() 2007-09-07 10:27:38 +00:00
edc50c89ee Promoted burn_drive_raw_get_adr() to API function burn_drive_d_get_adr() 2007-09-06 12:09:10 +00:00
ec5bb6eba5 Removed obstacles for use of stdio-drives 2007-09-06 10:01:28 +00:00
6f2b1c214e Added forgotten read/write counters in burn_stdio_write_track() 2007-09-06 10:00:20 +00:00
43a415a081 Added forgotten handling of pseudo-drives in burn_drive_grab() 2007-09-06 09:44:34 +00:00
277e3cfe29 Fixed a bug with failed opening of pseudo-drive 2007-09-05 19:53:50 +00:00
0c14e6ee4c burn_drive_grab_dummy() becomes invisible part of burn_drive_scan_and_grab() 2007-09-05 19:42:03 +00:00
6841cb68e5 Reacted on compiler warnings 2007-09-04 22:56:50 +00:00
970e2798ba Testing new API functions via --drive stdio:<path> 2007-09-04 22:51:44 +00:00
31650eb988 New API calls burn_drive_grab_dummy(), burn_drive_get_drive_role() 2007-09-04 22:50:04 +00:00
797f403b0d New API function burn_write_opts_get_drive() 2007-09-01 18:23:06 +00:00
65c0e34363 Adapted C code generator script to new address of libdax_model.txt 2007-08-29 15:10:43 +00:00
b5f1b465b0 Moved libdax-libcevap model stuff to libcevap/ 2007-08-29 15:02:04 +00:00
6d3c86690f Added missing file to link list: read.o 2007-08-29 12:45:01 +00:00
f5460ee843 Next cdrskin-0.3.9 cycle 2007-08-29 12:35:22 +00:00
47e0838a1e Work goes on 2007-08-29 12:30:02 +00:00
b8b3f85b2e Mentioned --grow_overwriteable_iso 2007-08-28 14:33:08 +00:00
070afd1a9b Made program behavior with --grow_overwriteable_iso more consistent 2007-08-28 14:31:42 +00:00
53634f23de New cdrskin option --grow_overwriteable_iso 2007-08-26 20:09:47 +00:00
dcf35bd556 More memory management changes proposed by Joris Dobbelsteen 2007-08-25 16:02:58 +00:00
bcb56b5e9e Reacted on false compiler warning about potentially unused variable 2007-08-25 09:10:48 +00:00
16a5bbacb4 Corrected memory management flaws found by Joris Dobbelsteen 2007-08-25 08:58:41 +00:00
5f66cf5d2f Try to read last 2 blocks of CD track without eventual error message 2007-08-23 15:06:05 +00:00
1adf86532e Allowed to suppress error message from failed burn_read_data() 2007-08-23 15:02:55 +00:00
c6bc4a5e97 Taking synchronous read/write into respect with abort handling 2007-08-22 17:33:53 +00:00
f37e109aa1 Avoided locked drive with interrupted telltoc read. (eject unlocks anyway) 2007-08-22 16:40:22 +00:00
2904a1bee7 Avoiding libburn read-ahead-bug 2007-08-22 16:13:44 +00:00
5066b0ac38 Retrieving my old backups which are hit by the Linux Read-Ahead-Bug 2007-08-22 14:05:03 +00:00
f567874c98 Corrected dangerous typo with error message production of mmc_read_10() 2007-08-22 13:46:21 +00:00
3127749f5c Added some function type declarations 2007-08-20 08:44:41 +00:00
4d78a15cbd Corrected a bug about inclusion of cevap*.h files 2007-08-20 08:43:44 +00:00
df9e6eac0b Corrected description of compiling and generating 2007-08-19 18:45:39 +00:00
9b552e9db6 Generator frontend scripts (./libcevap_gen.sh to be run in libcevap/) 2007-08-19 18:37:38 +00:00
99fceeb9e4 More comments, new capabilities of C code generator 2007-08-19 17:50:11 +00:00
88ad4a4ee1 The C code generator mentioned in doc/libdax_model.txt. See there. 2007-08-19 17:46:19 +00:00
ba0e977e42 Added more attributes and comments 2007-08-17 08:20:32 +00:00
d2c9236c25 Corrected harmless type declaration flaws 2007-08-17 08:19:30 +00:00
c7256fdc35 Added more attributes and distinguished read-write, read-only, private ones 2007-08-15 12:20:21 +00:00
a9ea78e9e7 Beautified implementation names and added some more attributes 2007-08-13 11:59:34 +00:00
0c3c4bceb6 Some polishing about option direct_write_amount= 2007-08-13 08:17:57 +00:00
7e86bcc417 Next cdrskin-0.3.9 cycle 2007-08-13 08:11:01 +00:00
22ea36ffd2 Testing burn_read_data() by option --read_and_print 2007-08-12 15:32:30 +00:00
d21697b289 New API function burn_read_data() 2007-08-12 15:25:56 +00:00
12b6a07e9f Debug message explaining why burn_drive_convert_fs_adr() acts on track source 2007-08-12 09:52:40 +00:00
ed06b376f2 Checked in burn_random_access_write() wether drive is grabbed 2007-08-12 09:51:04 +00:00
fd3a907d9f Clarifications about burn_random_access_write() 2007-08-12 09:48:31 +00:00
58e6577134 New option direct_write_amount= using new API call burn_random_access_write() 2007-08-11 20:22:52 +00:00
cf0dd395f0 New API function burn_random_access_write() 2007-08-11 20:16:57 +00:00
6950ac8c42 Reflected recent URL changes to libburnia-project.org 2007-08-11 07:51:04 +00:00
7958d0ce19 Changed project url in configure.ac to libburnia-project.org 2007-08-10 20:38:57 +00:00
1bd8012f10 Changed "libburn-1.pc" to "libburn-5.pc" to re-enable ./bootstrap ; ./configure 2007-08-10 20:29:59 +00:00
621a1c24e4 Updated comments about supported profiles and media types 2007-08-10 20:11:33 +00:00
3b310d3e19 Fiddled on the model attributes 2007-08-10 20:01:21 +00:00
4c92ab4dee Fixed build system of libburn and libisofs in respect to .pc files 2007-08-10 11:41:18 +00:00
97abb69301 Changed top-level URL in readme 2007-08-10 09:54:32 +00:00
b1eb7f1c65 Corrected typo in naming 2007-08-10 09:45:24 +00:00
c09a34ebe4 Corrected pc.in file according to our SO number 2007-08-10 09:44:59 +00:00
7f9fed74e1 Obscure backup of my unripe model ideas about libcevap (former libdax) 2007-08-09 13:33:55 +00:00
731d17581b Corrected a typo 2007-08-09 13:31:43 +00:00
0b575e044e Changed "unsigned" to "unsigned int" 2007-08-09 13:30:52 +00:00
5363693b07 Allowed speed=any 2007-08-09 13:28:40 +00:00
69f9f8e493 Corrected a dead link 2007-08-09 13:26:59 +00:00
4a7923ce4e Took into respect new info from Andy Polyakov about closing DVD+-R 2007-08-02 08:32:50 +00:00
23637b020e Corrected a harmless typo 2007-08-02 08:30:26 +00:00
605e66a005 Documented changes 2007-07-20 20:05:17 +00:00
5ff8e34d2c Updated cdrskin tarball generators 2007-07-20 18:55:50 +00:00
00df1c9b85 Made number transition to 0.3.9 2007-07-20 18:53:32 +00:00
7d23984220 Next cdrskin-0.3.7 cycle 2007-07-19 17:49:50 +00:00
aba535d700 Next cdrskin-0.3.7 cycle 2007-07-19 17:30:05 +00:00
203f158f5b Documented option --adjust_speed_to_drive (i.e. it will stay) 2007-07-19 17:27:26 +00:00
e274c90f9d Avoided new track-drive test with option --no_convert_fs_adr 2007-07-19 17:18:12 +00:00
bf25c6edc8 Trying to prevent usage of burn drive as track source 2007-07-19 14:29:59 +00:00
2c467c8378 Removed ban against speed 0 with burn_drive_set_buffer_waiting() 2007-07-19 07:23:01 +00:00
bdadae6ba5 Implemented minimum speed in burn_drive_set_speed() 2007-07-17 08:57:24 +00:00
1087d402f2 Clarification on option speed= 2007-07-17 08:55:10 +00:00
dc97c0d0df Experimental option --adjust_speed_to_drive. Caution: May vanish soon. 2007-07-14 11:23:16 +00:00
8b8afdd59b Only set realistic maximum DVD speeds (for my LG GSA which fails otherwise) 2007-07-14 11:22:01 +00:00
4dd8f098ac New API function burn_drive_get_best_speed() 2007-07-14 11:15:57 +00:00
16b6e1905a New options modesty_on_drive= and minbuf= 2007-07-12 17:31:57 +00:00
22d1d56ebd New API-Function burn_drive_set_buffer_waiting() 2007-07-12 17:17:41 +00:00
0217702b8c Preparations to avoid writing which will not fit in drive buffer 2007-07-12 16:29:29 +00:00
81d68aeb83 Changed "KB" to "kiB" 2007-06-10 08:06:03 +00:00
0e23721f2d Clarified MB to MiB if compatibility allows it (ticket 100) 2007-06-10 07:06:42 +00:00
3a771b3da2 Prevented macro interpretation of text snippet ".wav" 2007-06-08 10:56:15 +00:00
bacb815ecc Took into respect change of logo graphics format 2007-06-08 10:49:17 +00:00
f34d9efdb2 Changed logo graphics format from GIF to PNG 2007-06-08 09:59:29 +00:00
8efb863d5d Next cdrskin-0.3.7 cycle 2007-05-29 16:27:25 +00:00
d7ca1dd333 Fixed low transaction size introduced by cooperation of revisions 855 and 860 2007-05-28 19:25:09 +00:00
ddc2745495 Added check for .might_simulate to burn_write_opts_auto_write_type() 2007-05-28 17:03:12 +00:00
12c4c73535 Forgotten update of error list with revison 857 2007-05-28 16:59:49 +00:00
3326fcdb2d Extended struct burn_multi_caps by .might_simulate 2007-05-28 16:56:58 +00:00
fba8eaef80 Moved general 32 kiB buffer restriction from write.c to os-linux.h 2007-05-28 13:24:33 +00:00
15a70555b2 Added SCSI opcode to output of revision 857 2007-05-22 16:51:15 +00:00
83e196d69f Disabled macro Cdrskin_debug_libdax_msgS. Thus getting unqueued error messages. 2007-05-22 15:46:57 +00:00
c86f5d7cde Report eventual sg_io_hdr_t host_status,driver_status as debug messages 2007-05-22 15:45:57 +00:00
8d7d177ce3 Next cdrskin-0.3.7 cycle 2007-05-21 20:16:34 +00:00
cd7b4e6de4 For Linux 2.4, USB audio : Reduced CD output buffer size to 32 kiB 2007-05-21 19:03:06 +00:00
79adcb520b For Linux 2.4, USB : Carefully avoided to inquire more data than available 2007-05-21 18:57:09 +00:00
41f2a40a58 Prepared fflushing and stderr output of SCSI command log 2007-05-21 18:45:44 +00:00
9b663f15d9 Next cdrskin-0.3.7 cycle 2007-04-23 17:15:29 +00:00
ed9d3e2545 Updated cdrskin tarball generator 2007-04-23 15:48:40 +00:00
ba7cd6d66e Made number transition and activated development documentation 2007-04-23 15:43:51 +00:00
660bf40a3c Changed many /dev/sg to /dev/sr 2007-04-22 13:22:43 +00:00
25ba84a7e2 Repaired autotools bootstrap bug by help of sed 2007-04-22 12:20:33 +00:00
6566771834 Next cdrskin-0.3.5 cycle 2007-04-22 12:18:49 +00:00
2d2a2f8c1b Declared failure of DDLP to entirely solve the concurrency problem 2007-04-21 12:37:24 +00:00
329f266cea Beginning to develop DDLP-B 2007-04-20 21:16:17 +00:00
dce1ba57f3 Clarifications about motivation and duties of the participants 2007-04-19 11:34:54 +00:00
d3f08d4f96 Clarifications about motivation and duties of the participants 2007-04-19 11:31:59 +00:00
ddb63509af Corrected a list of standard paths 2007-04-18 21:48:45 +00:00
96098b3f2d Adaptations to new test results and discussions 2007-04-18 21:31:21 +00:00
256139c9d6 Polished messages, comments and description of DDLP-A 2007-04-18 13:01:21 +00:00
fd5b681bc6 Updated comments about DVD+R 2007-04-18 10:36:35 +00:00
2a38890c5f Progress due to tests with test/open-cd-excl 2007-04-18 10:35:38 +00:00
2ec2a34f51 Allowed for Friendly Programs: O_EXCL | O_RDONLY 2007-04-18 10:34:12 +00:00
10e320911a Program for probing access to device files. By Ted Ts'o with modifications by me. 2007-04-18 10:32:23 +00:00
9699880581 Corrected description of return values 2007-04-16 21:31:23 +00:00
13b9f910e1 Polished txt and finally threw out getter functions 2007-04-16 21:20:39 +00:00
acaba76cda Emerging description of DDLP 2007-04-16 19:45:11 +00:00
927a820aec Finalized DVD+R cookbook 2007-04-16 19:43:42 +00:00
3b9f66a765 Implemented ddlpa_lock_btl() 2007-04-15 20:34:27 +00:00
5d2ad006a4 Began test implementation of DDLP-A 2007-04-15 16:46:47 +00:00
aa03717f24 Made use of fcntl(F_SETLK) switchable (and thus became more free with default) 2007-04-13 17:28:25 +00:00
ab5f39b8bb Switched from O_NONBLOCK to O_NDELAY (see http://lkml.org/lkml/2007/4/11/141) 2007-04-13 17:12:06 +00:00
e1b8edb437 Clarified license. People who object shall please come forward now. 2007-04-12 14:47:59 +00:00
a78e6f9b29 Avoided SIGSEGV with an old SCSI CD-ROM drive and its wild replies 2007-04-10 14:46:46 +00:00
047f9c75f5 Fixed bug in sg_open_scsi_siblings() introduced with revision 802 2007-04-10 08:31:04 +00:00
159715ebaa Used O_EXCL|O_RDWR and fcntl() even within sg_obtain_scsi_adr() 2007-04-10 08:20:45 +00:00
f617567e03 Fixed bug with drive_scsi_dev_family= introduced by revision 796 (fcntl lock) 2007-04-10 08:17:07 +00:00
10a7a9d5e8 Next cdrskin-0.3.5 cycle 2007-04-10 07:58:19 +00:00
76ed9570c9 Reacted on compiler warning about last_rdev, fixed fresh typo bug 2007-04-09 11:10:41 +00:00
4bc8e4caea Cleaned up scsi sibling management, sketched grafting of DDLP 2007-04-09 10:54:17 +00:00
1a054b54c9 Updated media list in introduction comment 2007-04-06 06:49:51 +00:00
76a9fa4fa2 New cdrskin options --drive_not_f_setlk and --drive_not_o_excl 2007-04-04 18:43:23 +00:00
4c85686aad Added fcntl() locking to O_EXCL locking 2007-04-03 14:58:17 +00:00
a686340407 Make --old_pseudo_scsi_adr -scanbus work with any drive_scsi_dev_family= 2007-04-03 14:56:36 +00:00
16c7cf1889 Added fcntl() locking to O_EXCL locking 2007-04-03 14:04:04 +00:00
15b33422d0 Avoided unconditional finalizing of DVD+R 2007-03-30 21:47:56 +00:00
649f67697a Allowed finalizing of DVD+R 2007-03-30 20:11:36 +00:00
125e28160d Next cdrskin-0.3.5 cycle 2007-03-29 08:18:34 +00:00
eb860ee4b7 Silenced error message if tsize= is smaller than source is willing to deliver 2007-03-28 20:25:22 +00:00
a8c69206fe Made fifo based -isosize read 64k first and the rest only at normal stage 2007-03-28 18:21:46 +00:00
26745b4064 Enabled -isosize with S_IFREG or S_IFBLK files and without fifo 2007-03-28 16:02:26 +00:00
962f68b1d6 Silenced error condition about -sao with stdin and -isosize 2007-03-28 11:15:04 +00:00
cc5560fc86 Enabled -isosize for first track by help of fifo and without seeking 2007-03-28 10:07:09 +00:00
5d65697697 Preparations for option -isosize via fifo (only a debug message yet) 2007-03-27 21:33:22 +00:00
749d12591e Warning of very small tsize= settings. (Proposal by Eduard Bloch) 2007-03-24 09:34:56 +00:00
98f0dab87e Fixed bug with burn_disc_available_space(...,NULL) 2007-03-24 09:31:11 +00:00
17c87b78a6 Mentioned new sr behavior 2007-03-18 11:03:08 +00:00
ecbe1c0f39 Next cdrskin-0.3.5 cycle 2007-03-16 00:10:46 +00:00
9507587652 Updated drive_scsi_dev_family= 2007-03-15 20:34:08 +00:00
dba40c756b Trying to recognize kernel >= 2.6 and use /dev/sr by default 2007-03-15 19:59:54 +00:00
fd9e5dc935 Kept mmc_get_configuration() from believing the announcement of 1 GB reply 2007-03-15 19:55:17 +00:00
2816d8b569 Moved manual device family decision to a sufficiently early stage 2007-03-15 19:54:01 +00:00
64233b0ccc After loading tray wait for unit to become ready or to report some clear error 2007-03-15 19:50:57 +00:00
9e1b3719d6 React properly on drive stating that it cannot write any media 2007-03-15 19:46:26 +00:00
6086b59301 New option drive_scsi_dev_family=sr|scd|sg 2007-03-14 13:37:32 +00:00
c345426299 Next cdrskin-0.3.5 cycle 2007-03-14 13:15:00 +00:00
05216162ef Corrected truncated sentence and file sizes 2007-03-14 13:12:28 +00:00
13e2b23ace Updated cdrskin tarball generator 2007-03-12 16:01:51 +00:00
820f0924f9 Made number transition to 0.3.5 2007-03-12 15:58:19 +00:00
5b6aab575e Polished documentation 2007-03-10 11:49:49 +00:00
bd529442ed New option assert_write_lba= 2007-03-09 13:43:57 +00:00
33938c20eb Polished documentation 2007-03-08 21:55:50 +00:00
71c490d0ae Some adjustments for DVD+R recording 2007-03-07 15:13:25 +00:00
4458bb130a Enabled DVD+R as tested media (-multi is still always on) 2007-03-06 20:51:32 +00:00
99172bdeb4 Enabled DVD+R, DVD+R DL via --allow_untested_media_types, always -multi for now 2007-03-06 19:50:32 +00:00
790c75be9c Released cdrskin-0.3.2.pl01 2007-03-05 20:07:43 +00:00
6a5e1b6bd5 Fifo got stuck if sum of processed track sizes was exactly aligned to fifo size 2007-03-04 18:45:52 +00:00
49e0a6cb1a Fixed bug introduced with rev 736ff which prevented audio CD burning 2007-03-03 15:16:19 +00:00
b6c7fd7478 Re-enabled -force with write modes which seem unavailable 2007-03-03 14:11:52 +00:00
e955d50198 Determine physical interface SCSI,ATA,SATA,USB,... (for future use) 2007-03-03 14:09:46 +00:00
794d1ee712 Updated DVD-R[W] write mode description 2007-03-03 09:00:28 +00:00
3b5c80e867 Preparations for supporting DVD+R[/DL] 2007-03-01 12:07:29 +00:00
0c4cfdd359 Took into respect deliberate lack of DVD-R/DL multi session capability 2007-02-25 11:26:20 +00:00
f263443858 Forgotten source file for revision 743 2007-02-23 19:33:56 +00:00
362a8faa61 Enabled DVD-R/DL Sequential via --allow_untested_media_types 2007-02-23 19:10:30 +00:00
2e361e50ed Enabled DVD-R/DL Sequential via burn_allow_untested_profiles() 2007-02-23 19:08:58 +00:00
0ddeb01502 Made burn_disc_available_space() take into respect burn_write_opts_set_start_byte() 2007-02-22 11:30:12 +00:00
64ae333863 Macro for length of rejection reasons string (old size is still safe) 2007-02-22 09:49:18 +00:00
9f2c4b303d Disabled debugging messages about format descriptors 2007-02-22 07:31:32 +00:00
8182be7824 Re-enabled overwriteable pseudo-pseudo-SAO with unpredicted track size 2007-02-22 07:26:41 +00:00
fa6849374a Added -O2 to binary production 2007-02-21 20:57:04 +00:00
115f03cf63 Moved tao_to_sao_tsize into libburn, let cdrskin use auto_write_type and precheck 2007-02-21 20:53:28 +00:00
b6475c3d84 Re-arranged checking and defaulting of write parameters 2007-02-19 22:51:39 +00:00
afd54a1f87 Repaired slightly broken pacifier track size display with -audio 2007-02-19 18:41:38 +00:00
4f3dd8614d Adjusted maximum realistic number of tracks to MMC specs 2007-02-18 09:49:26 +00:00
7989d32834 Next cdrskin-0.3.3 cycle 2007-02-18 09:48:00 +00:00
0151358635 Clarified usage comment with burn_drive_info_free() (see ticket 98) 2007-02-18 09:44:44 +00:00
8c0e0a7a47 Removed unprecise unnecessary comment 2007-02-17 09:09:34 +00:00
c570e4868d Allowed forceful blanking of blank media in burn_disc_erase() 2007-02-17 08:56:41 +00:00
6ccd359c93 Another bug fix for revision 724 2007-02-17 08:52:07 +00:00
ca69e3f2ca Corrected CD TAO bug introduced with DVD bug fix 724 and CD SAO change 655 2007-02-16 11:21:01 +00:00
d272450a70 Repaired debugging message spoiled by uninitialized variable 2007-02-15 20:35:57 +00:00
a21c2a5138 Clarifications about current state of fillup 2007-02-15 20:23:49 +00:00
73273b1643 Corrected bug about open_ended filluped tracks 2007-02-15 20:19:07 +00:00
4df7aa0f3b Installed a guardian for predicted track end 2007-02-15 20:18:07 +00:00
dbe2ee41ae Took fill_up_media into respect with automatic write mode decisions 2007-02-15 20:16:22 +00:00
72a2ef9f96 New options --fill_up_media and --tell_media_space 2007-02-14 20:38:04 +00:00
e639cd5bbb Optional padding up to full media size when closing (incomplete yet) 2007-02-14 20:32:56 +00:00
3ec93316e0 Forgotten part of revision 718 2007-02-14 12:23:51 +00:00
ff6a9fc92b Handle eventual ridiculously high d->last_track_no 2007-02-14 12:20:32 +00:00
636f5278ad Set the advised write mode before inquiring media space 2007-02-14 12:05:26 +00:00
e10bfe2d37 Removed outdated ifdef 2007-02-14 12:03:47 +00:00
4da50dfad5 Applied new API function burn_disc_available_space() 2007-02-13 14:39:34 +00:00
dc281902a5 Removed or updated outdated restriction statements 2007-02-13 14:38:14 +00:00
4903bb9971 Mew API function burn_disc_available_space() 2007-02-13 14:37:25 +00:00
ba702bc9a8 Set a suitable page 05h after spc_probe_write_modes() 2007-02-13 11:55:09 +00:00
c7804d390f Made profile 0010h DVD-ROM suitable,full,not erasable. So it delivers a TOC. 2007-02-12 14:23:14 +00:00
9584adcc87 Updated list of keywords 2007-02-12 12:42:23 +00:00
7154d8cb91 Being exacting about on-the-fly and DVD-RW 2007-02-12 12:41:18 +00:00
36b4f2ded5 Documented changes and 0.3.2 release timestamp 2007-02-10 17:24:50 +00:00
1aed3f692c Added a comment about DVD-R 2007-02-10 17:23:49 +00:00
fdcb1a4014 Updated cdrskin tarball generator 2007-02-10 17:15:12 +00:00
384c47c710 Made number transition and activated development documentation 2007-02-10 17:13:41 +00:00
e8d210e15f Small corrections in documentation 2007-02-09 16:14:47 +00:00
6df2745652 Added special thanks towards Andy Polyakov 2007-02-09 16:01:45 +00:00
09b5bd2a1f Silenced compiler warning 2007-02-08 22:53:22 +00:00
67ce096aeb Mentioned DVD-R 2007-02-08 21:29:33 +00:00
cad7531058 New option --prodvd_cli_compatible 2007-02-08 21:09:10 +00:00
8dccb584b4 Finally made tests with DVD-R. They burn indeed like DVD-RW. 2007-02-08 14:10:05 +00:00
50eba7ee31 Updated documentation aspects 2007-02-07 17:49:52 +00:00
494693cc63 Made use of burn_write_opts_auto_write_type() 2007-02-07 16:37:25 +00:00
05623cffc4 New API function burn_write_opts_auto_write_type() 2007-02-07 16:30:42 +00:00
fed2af8c69 Next cdrskin-0.3.1 cycle 2007-02-06 21:22:41 +00:00
78f1cf835d Described DVD-R[W] DAO mode 2007-02-06 19:21:20 +00:00
d2283a5b4e Clarified CD and DVD peculiarities 2007-02-06 19:19:54 +00:00
8dd8ee4b9c Enabled fast blank for DVD-R[W] 2007-02-06 18:57:38 +00:00
6dfbbdf57f tao_to_sao_tsize= for DVD-R[W] DAO 2007-02-06 17:45:17 +00:00
d57166f64b Beautification of debugging messages 2007-02-06 17:08:15 +00:00
2799fe1b44 Implemented DVD-R[W] DAO as BURN_WRITE_SAO 2007-02-06 13:06:39 +00:00
330e0e2d5f Preparations for DVD-R[W] DAO 2007-02-05 13:28:57 +00:00
135d9d5016 New in API : struct burn_multi_caps and burn_disc_get_multi_caps() 2007-02-04 07:30:14 +00:00
db9f4a1d04 Mentioned DVD-RW multi-session 2007-02-03 18:46:42 +00:00
6b8ab52854 Improved classification and TOC of finalized DVD-R[W] media 2007-02-02 17:32:09 +00:00
4e93de2cd2 Make mmc_read_multi_session_c1 use TOC if available 2007-02-02 15:11:35 +00:00
a769f8aa87 Updated about DVD-R[W] blanking, multi-session info and TOC 2007-02-02 13:39:30 +00:00
e0a38be97b Some sed expressions for beautification 2007-02-02 13:37:34 +00:00
100de7b160 Mentioned DVD-RW multi-session in overview of features 2007-02-01 20:14:01 +00:00
9f7e5dd6dd Mentioned DVD-RW multi-session in overview of features 2007-02-01 20:06:03 +00:00
a9ac7ae480 Prepared next cdrskin-0.3.1 cycle 2007-02-01 19:53:07 +00:00
2e75680ed7 Prepared next cdrskin-0.3.1 cycle 2007-02-01 19:45:47 +00:00
c02dbe4eca Allowed blanking of DVD-RW which offer no Incremental Streaming 2007-02-01 19:15:06 +00:00
f3a08f6812 Reacted on justified compiler warning about unitialized sessions variable 2007-02-01 16:33:27 +00:00
e876f90e6c Obtain TOC from non-CD via 52h READ TRACK INFORMATION 2007-02-01 16:15:09 +00:00
dde52c1971 Provisorily obtain multi-session -C parameters (violates MMC specs but works) 2007-01-31 17:34:49 +00:00
f194aa8d5d Blank sequential DVD-RW, deformat overwriteable DVD-RW 2007-01-31 12:59:51 +00:00
b18b889750 Enabled Burnfree buffer underrun protection by default 2007-01-30 22:01:10 +00:00
0aafc18ac7 Added snapshot of emerging sequential DVD-R[W] cookbook 2007-01-30 20:16:55 +00:00
fa792f6a67 First successful multi-session write to a sequential DVD-RW 2007-01-30 19:16:35 +00:00
53a1e99675 Preparations for DVD-R[W] Sequential Recording 2007-01-30 17:54:39 +00:00
bda139f390 Experiments about list of features and profiles 2007-01-29 17:57:31 +00:00
ff7028d1fc Added a statement about blanking of DVD-RW 2007-01-29 17:52:36 +00:00
fa350edaae Initialized member set_size of burn_source within burn_null_source_new() 2007-01-26 17:33:29 +00:00
55e6c0ba82 Unified burn_file_source and burn_fd_source 2007-01-26 17:32:31 +00:00
f5a350f2cc Now offering cdrskin-0.3.0.pl01 for download 2007-01-26 11:09:07 +00:00
c079e09860 Enforce minimum track length with SAO 2007-01-25 18:52:50 +00:00
99f8e0eec5 Bug fix: DVD tracks of defined size >=2GB suffered 32-bit integer wraparound 2007-01-25 15:00:37 +00:00
3aec7fdeda Restored FreeBSD backend. 2007-01-24 12:44:22 +00:00
814d8cc83d Removed libisofs specific bits. 2007-01-24 12:41:25 +00:00
bc694d7457 Corrections of typos and text debris 2007-01-23 21:34:13 +00:00
66d70075ec Added SAO CD Cookbook 2007-01-23 10:35:51 +00:00
8f4dd8580c Banned mixed mode SAO (because broken in libburn and unclear in MMC) 2007-01-22 11:42:17 +00:00
7dd845a83b Clarification about TAO and mode page 05h per track 2007-01-21 19:13:27 +00:00
7b024f4a72 Comments learned from studying MMC-3 and MMC-5 for SAO CD cookbook 2007-01-21 19:10:37 +00:00
f1215f3295 Removed unnecessary after-grab loops 2007-01-21 19:09:07 +00:00
8e17806405 Changes with CD part. Especially explanation of TOC. 2007-01-20 14:26:32 +00:00
fb98c0390e Began to describe TAO multi-session CD writing 2007-01-19 20:54:11 +00:00
f418c49e63 Removed forgotten debug message printed to stderr 2007-01-19 11:05:18 +00:00
a34e872511 Kept DVD+RW from stopping BG formatting if it was not started at all 2007-01-18 21:18:03 +00:00
69a07aeec6 Made clarification about formatting state recognition 2007-01-18 21:16:13 +00:00
7addf0d5b5 More info about Current/Maximum Capacity Descriptor 2007-01-18 14:33:53 +00:00
a001f96b21 Wrote down what i learned from implementing support for overwriteable DVD 2007-01-18 13:55:28 +00:00
4a26017f2a Removed paragraph about obsoleted tao_to_sao_tsize= 2007-01-17 13:00:05 +00:00
0f48910aff Next cdrskin-0.3.1 cycle 2007-01-16 15:44:39 +00:00
c68efb346c Corrected typo 2007-01-16 15:18:34 +00:00
36f287d569 Corrected old libburn.pykix.org URL 2007-01-16 15:15:08 +00:00
4d7e28c09f Made version number transition to 0.3.1 2007-01-16 15:11:41 +00:00
c1342195f6 Updated cdrskin tarball generator 2007-01-16 15:07:09 +00:00
1fd003c1ec Next cdrskin-0.2.7 cycle 2007-01-15 15:30:41 +00:00
36d475eaf9 Updated about overwriteable DVD and pointer to dvd+rw-tools 2007-01-15 12:58:49 +00:00
9180a0036d Avoided closing of 0x13-DVD-RW sessions which are not intermediate 2007-01-14 13:41:19 +00:00
f28ec96709 Added missing cache sync in case of aborted DVD-RW burns 2007-01-14 11:55:17 +00:00
16baf48b2e Corrected bug with debug messages for fifo 2007-01-14 10:19:10 +00:00
caef0aa400 Shifted fifo reporting to new 4-times -v verbosity level 2007-01-13 21:45:04 +00:00
fefdbc646f Mentioned DVD-RAM where appropriate 2007-01-13 21:20:56 +00:00
44cd12a0a0 Added printing of list of available formats 2007-01-13 21:20:05 +00:00
07cef29616 Introduced API for inspection and selection of format capacities 2007-01-13 21:18:20 +00:00
a426df57d7 Load array of format capacities into struct burn_drive 2007-01-13 21:16:04 +00:00
a2f8174330 Documentation updates about DVD-RAM 2007-01-13 14:12:07 +00:00
b6025c6e4a Implemented debugging messages for ATA enumeration 2007-01-13 14:10:21 +00:00
ceb5159770 Implemented debugging messages for ATA enumeration 2007-01-13 14:09:53 +00:00
f77dd3134b Enabled writing to DVD-RAM 2007-01-12 16:26:31 +00:00
c381104505 Removed surplus newlines from messages 2007-01-11 13:35:48 +00:00
d61f1279c1 Sketched better handling of self-inflicted SIGs 2007-01-11 13:34:41 +00:00
0f34fb03a0 Kept SIGWINCH from spoiling a burn. 2007-01-11 13:31:28 +00:00
ef6212f4ec With full formatting prefer format 10h over 13h or 15h 2007-01-11 13:29:39 +00:00
fcc9f8fe8e Removed outdated option from startup file example 2007-01-11 13:28:36 +00:00
8877b36625 Enabled explicit full formatting of DVD+RW ("de-icing") 2007-01-10 21:07:48 +00:00
435eeea15f Removed writing of dummy data with blank=format_overwrite_full 2007-01-10 15:30:54 +00:00
15af71d448 Switched full formatting from type 10h to 00h which includes lead-out 2007-01-10 15:27:54 +00:00
27262bde51 Option -force enables re-formatting 2007-01-10 15:26:30 +00:00
7bf228954c Next cdrskin-0.2.7 cycle 2007-01-10 15:22:48 +00:00
071feccd32 Updated size estimation of development downloads 2007-01-10 15:21:42 +00:00
f1b817b520 Now available: "quickest" and "full" formatting for DVD-RW 2007-01-09 21:14:47 +00:00
e6cfff69eb Enhanced DVD-RW formatting 2007-01-09 21:06:55 +00:00
5fc55ec164 Fixed a SIGFPE with formatting via libburner 2007-01-09 14:03:43 +00:00
7211f210dc Using 128 MB of size plus writing of zeros with blank=format_overwrite 2007-01-08 10:44:34 +00:00
fdd40d4492 Introduced size parameter to DVD-RW formatting plus writing of zeros. 2007-01-08 10:42:54 +00:00
6a69cfcf07 Added note that buffer may not be smaller than 32768 2007-01-08 10:30:30 +00:00
ab51d551d3 New formatting parameter "size". Sorry for changing API. Function is a week old. 2007-01-06 12:08:57 +00:00
f6b751c4bd Comments and name changes from new findings out of reading MMC-5 2007-01-05 12:58:36 +00:00
f23deebe80 Moved blanking suitability test before eventual spwaning of threads 2007-01-03 16:49:09 +00:00
b362f80d40 Made formatting report progress (as good as the drive does) 2007-01-03 16:42:53 +00:00
f634a52e86 Some DVD-RW statements 2007-01-02 18:40:09 +00:00
441c2a32cd Made use of formatting of DVD-RW 2007-01-02 12:57:47 +00:00
bee5484d46 Some DVD-RW statements 2007-01-02 12:54:42 +00:00
342283ffea Next cdrskin-0.2.7 cycle 2007-01-02 10:58:34 +00:00
cb24c90f0c Greeting the new year 2007-01-02 09:10:44 +00:00
1824c065f0 Added links to cdrskin help texts 2007-01-02 09:04:38 +00:00
9e4c2866a9 Made use of formatting of DVD-RW 2007-01-01 17:19:41 +00:00
97fe858760 Prepared formatting of DVD-RW 2007-01-01 17:10:54 +00:00
ca9d11c692 Next cdrskin-0.2.7 cycle 2006-12-30 00:19:38 +00:00
c05d6550cb Prepared support for DVD-RW in mode Restricted Overwrite 2006-12-30 00:15:07 +00:00
6e9c399930 Corrected DVD-RW sequential profile name 2006-12-29 14:39:42 +00:00
7c6895aec2 Updated about msifile=path 2006-12-27 21:44:17 +00:00
a9e4bc1dbd Followed revision 644 of wodim (msifile output without newline) 2006-12-27 21:39:02 +00:00
5f4e9d9cfb Emulated wodim option -msifile=path 2006-12-27 16:30:25 +00:00
c4fe384b56 Avoided self contradicting result of ATIP speed inquiry 2006-12-27 13:28:40 +00:00
b2cf633bdc Defended against a race condition on SuSE 9.3 after -atip (hald et.al. ?) 2006-12-27 13:04:17 +00:00
13ecca61bc Corrected kB conversion factor to 176.4 with ATIP speed codes 2006-12-27 13:03:09 +00:00
6277678a8e Disabled obsolete drive-media-state workaround. (Spinoff of ticket 93 :)) 2006-12-27 13:01:39 +00:00
cafad767a9 Minor corrections to revisions 559 and 560 2006-12-26 18:45:21 +00:00
18ba02c2bb Enabled report of speed descriptor list 2006-12-26 17:08:46 +00:00
85ffe77a32 New API calls burn_drive_get_speedlist() , burn_drive_free_speedlist() 2006-12-26 17:07:53 +00:00
95bebfb814 Completed revision 556 2006-12-25 19:07:43 +00:00
1b68e65005 Adjusted to new (more mature) speed info semantics 2006-12-25 19:01:25 +00:00
979e35d979 Ticket 93: write speeds from ACh GET PERFORMANCE, Type 03h, DVD media capacity 2006-12-25 19:00:26 +00:00
d4711abba8 Corrected CD speed conversion factor to 2352*75/1000 = 176.4 kB/s 2006-12-25 18:57:11 +00:00
d53114b723 Adjusted to new (still immature) speed info semantics 2006-12-25 11:37:24 +00:00
a4846ef882 Ticket 93: write speeds from mode page 2Ah descriptors 2006-12-25 11:34:43 +00:00
00afac796e Removed unnecessary waiting loops after grab, mentioned DVD+RW 2006-12-24 20:24:43 +00:00
42c0cc6dd4 Bugfix after changes for DVD+RW: start_byte was initialized 0, but must be -1 2006-12-24 18:23:30 +00:00
221aee23d1 Bugfix with DVD+RW : progress indicators were initialized too late 2006-12-24 18:22:27 +00:00
c3a5d3c7a5 Made DVD ignore CD write modes of drive. Made TAO default for DVD+RW. 2006-12-24 15:47:11 +00:00
a7610aa0c9 Made DVD 32k end padding controllable 2006-12-24 14:24:35 +00:00
fb4a209a34 Fixed a bug with speed measurement at end of DVD+RW burning 2006-12-24 14:22:38 +00:00
9ba4f5f3df Made Jean name more friendly 2006-12-23 22:00:43 +00:00
745c8ca611 Modified cdrskin_timestamp 2006-12-23 21:56:39 +00:00
2f007fcb36 Added Jean to contributors 2006-12-23 18:56:29 +00:00
7e30dbfc5a More appropriate drive status during format and close of DVD+RW 2006-12-23 18:43:31 +00:00
1ce6ec4a3a New API function to inquire burn success (and avoid confusing messages) 2006-12-23 14:12:55 +00:00
750b897ef0 Added more info about DVD+RW 2006-12-23 11:24:11 +00:00
c6555dd8f5 New option write_start_address= 2006-12-23 10:21:44 +00:00
c09d8e6da6 Adjustable write position for DVD+RW: burn_write_opts_set_start_byte() 2006-12-23 10:20:35 +00:00
9d65aa1c40 Some bragging about DVD+RW 2006-12-21 21:46:58 +00:00
59d3e7296b Report media type, avoid self contradicting messages with DVD+RW --multi 2006-12-21 20:58:26 +00:00
9a752c6130 Disallowed multi flag with DVD+RW (nurses wrong hopes for now) 2006-12-21 20:57:15 +00:00
ce27ad5159 DVD speed setting via B6h SET STREAMING, DVD+RW now enabled in vanilla build 2006-12-21 20:06:04 +00:00
1f3c3fe622 DVD speed reporting (and setting for drives which obey BBh SET CD SPEED) 2006-12-21 12:25:38 +00:00
ff755e7204 Removed some debugging messages 2006-12-21 12:23:10 +00:00
4a2402171a With -atip on DVD report no RAW/RAW96R among "Supported modes" 2006-12-20 19:54:46 +00:00
8d54a56590 With -atip report "booktype" for DVD media and no questionable ATIP info 2006-12-20 18:02:34 +00:00
dae337de09 Corrected bug reported by gcc -O2 2006-12-20 17:40:38 +00:00
adaf3f20d7 Corrected bug reported by gcc -O2 2006-12-20 17:13:05 +00:00
de33492cde Corrected DVD+RW track number and nwa with 52h READ TRACK INFORMATION 2006-12-20 17:05:33 +00:00
1b1ef5a31d Avoid undefined 43h commands (TOC/ATIP) with non-CD 2006-12-20 14:52:48 +00:00
b02b2a40e7 Refuse to burn audio tracks to DVD 2006-12-20 14:23:36 +00:00
94848398c0 Prepared experiments for writing to DVD (most easy: DVD+RW) 2006-12-20 11:20:08 +00:00
c1f49bab3b Noted some insight about necessity of OPC gained from growisofs_mmc.cpp 2006-12-18 12:33:51 +00:00
4778a57c53 Made several minor clarifications 2006-12-18 12:29:20 +00:00
ea923c391a Introduced term "session" 2006-12-15 16:14:20 +00:00
0aec5f2981 Adapted to changes in cdrskin.1 2006-12-15 10:27:08 +00:00
59a8cfc0d4 Clarified drives and their addresses 2006-12-15 10:15:50 +00:00
99eeb27688 Adapted to existence of man page 2006-12-14 17:15:22 +00:00
336c599741 Added some meta info to the document header, changed title to "man 1 cdrskin" 2006-12-14 17:14:17 +00:00
f095e04165 Next cdrskin-0.2.7 cycle 2006-12-14 14:07:47 +00:00
409c086581 Corrected alphabetical sorting error 2006-12-14 14:06:23 +00:00
0f1d433d5b Re-arranged examples of documentation commands 2006-12-14 14:05:24 +00:00
deed90b65e Removed outdated experiment 2006-12-14 11:03:46 +00:00
ab08d66af3 Publishing cdrskin.1 as man_1_cdrskin.html 2006-12-14 10:29:03 +00:00
3acd08b34b Mentioned George Danchev for his merits about cdrskin man page 2006-12-14 10:23:42 +00:00
d187efea4d Unified some nomenclature. Removed an error with dev_translation= 2006-12-14 10:22:17 +00:00
ed5eb49b18 Explained recordable CD media. Removed a typo. 2006-12-13 23:24:23 +00:00
c9fc338174 Next cdrskin-0.2.7 cycle 2006-12-13 22:33:52 +00:00
8c6c78ed4e Took more care for man page 2006-12-13 22:20:16 +00:00
2dea8b0f60 Clarified track content meaning. Corrected some typos and beauty flaws 2006-12-13 22:12:36 +00:00
0160a98e67 Took care for man page 2006-12-13 22:09:42 +00:00
84b87f4eb5 Trying to get new man page into release tarball and installation. 2006-12-13 19:54:55 +00:00
4c70280527 Detailed man page for cdrskin. Based on work of George Danchev. 2006-12-13 19:30:31 +00:00
178a0305c5 Updated dev=help to versions >= 0.2.4, new option --list_ignored_options 2006-12-13 17:03:46 +00:00
fcf9c50220 Appeased doxygen warnings 2006-12-11 21:51:00 +00:00
17bac86aae Trying to identfy CD device via ioctl(CDROM_DRIVE_STATUS) 2006-12-11 19:19:15 +00:00
d9e502ee5f Reacted better on failing ioctl(SG_GET_SCSI_ID) 2006-12-11 16:20:54 +00:00
17fc8e7161 Removed ban on linux_sg_device_family, warning now of linux_sg_accept_any_type 2006-12-11 14:54:26 +00:00
e405092ab0 Enabled correct SCSI address parameter registration for /dev/srM 2006-12-11 13:45:50 +00:00
c6d22a1eb0 Prevented SIGSEGVs when using -atip with my SCSI CD-ROM (sr,sg: no matter) 2006-12-11 12:53:12 +00:00
8265834404 Silenced a compiler warning. Worked further on /dev/srM test. Not done yet. 2006-12-11 11:58:52 +00:00
592b52df5e Repaired README link and planted helptext links 2006-12-11 11:57:21 +00:00
4d62e6003f Consequences from newly introduces startup file 2006-12-11 10:14:43 +00:00
77f44ce5a2 Prepared experiments for new Linux SCSI adventures 2006-12-11 10:01:18 +00:00
5ecd7455ac Unified mix of tab an blanks which looks ugly in diff 2006-12-11 09:58:57 +00:00
bb951e0538 Belated timestamp for changes in cdrskin 2006-12-11 09:56:59 +00:00
1677d40e91 Next cdrskin-0.2.7 cycle 2006-12-11 09:56:09 +00:00
4c0d113956 Added autoreconf-needed files - libburn tree 2006-12-10 17:08:28 +00:00
ae338b8f2c Added dummy NEWS, Changelog, and Install - libburn tree 2006-12-10 17:06:28 +00:00
d5eda47306 Added Gabriel to contributors 2006-12-10 16:34:52 +00:00
9a0442b60c Made cdrskin configuration more friendly to other distros 2006-12-10 16:32:19 +00:00
c4c571f7e3 Replaced setuid blocker by warning. People must know themselves what they do. 2006-12-09 11:09:42 +00:00
81c86161a7 Fixed build system autoconf-related bug 2006-12-04 22:01:21 +00:00
003c72a396 Added reporting of current media profile, changed "Media type" to "Media reuse" 2006-12-04 18:30:20 +00:00
13f77b4428 Removed a newline which made the Mozilla family show a "_" 2006-12-04 17:21:36 +00:00
80f5923e90 Next cdrskin-0.2.7 cycle 2006-12-03 23:07:38 +00:00
165e83b692 Excluded doener gifs from cdrskin tarballs 2006-12-03 20:52:43 +00:00
e1b2beea4e Added Doener logo and link 2006-12-03 17:20:43 +00:00
bab1cf96c6 Changed URLs and umbrella names to libburnia 2006-12-03 16:52:55 +00:00
aafc0b0be2 Changed URLs and umbrella names to libburnia 2006-12-03 15:56:27 +00:00
915e24a0c2 Have wikipedia explain doenerism ("Eat the rich" and so) 2006-12-03 14:24:04 +00:00
7d7c19b628 cdrskin is declared honoray Doenerware (burp) 2006-12-03 13:16:24 +00:00
f6ce7ca8ce Testing wether the after-grab status waiting loops are necessary 2006-12-02 20:14:56 +00:00
e29f13980b Avoided unsuitable media complaint on burn_drive_grab() with load==0 2006-12-02 20:13:31 +00:00
90d0a6952c Next cdrskin-0.2.7 cycle 2006-12-02 17:03:38 +00:00
91ff41856b Correction for drives which return empty tray as profile 0x00 rather than error 2006-12-02 13:06:05 +00:00
229328e869 New API function to obtain media type: burn_disc_get_profile() 2006-12-02 11:17:12 +00:00
ad2c080145 Ticket 21: media type via 46h GET CONFIGURATION , Current Profile 2006-12-01 21:38:34 +00:00
6869e12e4d Added preliminary support for new cdrecord 1000+ = ATA busses (input only) 2006-11-29 20:51:58 +00:00
0e3fb8d620 Mentioned renaming of umbrella project to libburnia 2006-11-28 11:55:08 +00:00
221aa948e4 Enabled options -vv, -vvv and -vvvv 2006-11-25 21:05:14 +00:00
9270f41c65 Prevented premature BURN_DRIVE_IDLE introduced with revision 443 2006-11-25 18:30:06 +00:00
3d5cb04093 Trying to keep signal handler from repeating messages 2006-11-25 17:06:17 +00:00
15df1d819c Corrected two minor bugs 2006-11-25 16:05:23 +00:00
11f16316b1 Made use of libburn device address translation (/dev/sr0, /dev/cdrom, ...) 2006-11-25 15:43:31 +00:00
56ab215db0 Ticket 91: update media state model after content change 2006-11-25 15:26:35 +00:00
13214d9ac5 Disabled old workaround for ticket 8, burn_disc_read_atip() fixed the problem 2006-11-25 10:42:22 +00:00
c67bd685a2 Made our claim of burning CD more general 2006-11-24 16:28:25 +00:00
d20c4fee8c Updated libburner helptext copy 2006-11-24 16:18:42 +00:00
ba982ebf64 First cdrskin-0.2.7 cycle 2006-11-24 16:15:58 +00:00
5bd74c3064 Mentioned telltoc and dewav as helpers of libburner 2006-11-24 12:41:39 +00:00
5cdc9db76c Version leap to 0.2.7 2006-11-24 12:19:43 +00:00
de02cc26f9 Version leap to 0.2.6 2006-11-23 10:26:18 +00:00
35a1a1f7d7 Removed obsolete test programs 2006-11-23 09:10:03 +00:00
54d3702513 Last cdrskin-0.2.5 cycle 2006-11-23 07:20:53 +00:00
c3f9764e0a Made doc system buildable 2006-11-22 22:40:32 +00:00
ab4096e720 Switched to 0.2.6 cycle before release 2006-11-22 22:28:14 +00:00
26fa325ee4 Coordinated scsi_notify_error() and scsi_error() 2006-11-22 12:25:16 +00:00
314027631a Updated in respect to multi-session 2006-11-20 14:39:25 +00:00
6e09b56c29 Implemented new option fifo_start_at= 2006-11-20 13:30:01 +00:00
08f541a7a8 Next cdrskin-0.2.5 cycle 2006-11-20 13:25:27 +00:00
26412b4793 Removed a redundant d->start_unit() of revision 419 2006-11-20 09:07:47 +00:00
9ea689d7e4 Silenced compiler warnings 2006-11-20 09:06:30 +00:00
f3b994f845 Fixed missing brackets from revison 421 2006-11-19 16:40:53 +00:00
46906c7f65 Avoided self contradiction with "Min drive buffer fill" 2006-11-19 16:32:09 +00:00
4daed7c4a9 Implemented libburn builtin fine granulated drive buffer min-fill recording 2006-11-19 11:47:34 +00:00
ebb94ee212 Test wether SCSI 1Bh START UNIT would be helpful with ticket 90 2006-11-18 19:49:18 +00:00
18a592ad28 Shifted a comma 2006-11-17 21:30:25 +00:00
ba48efbc52 Shifted a comma 2006-11-17 21:29:19 +00:00
0513a4eb2f Obsoleted old test program 2006-11-17 20:15:14 +00:00
254852ee36 Enabled multi-session with libburner 2006-11-17 19:51:51 +00:00
ef6d76c22d Created info retrieval companion for libburner 2006-11-17 19:38:28 +00:00
66c3ead5d6 Updated help text of libburner 2006-11-16 16:53:42 +00:00
908a6b336b Obsoleted --stdin_size by automatic TAO. Cared for non-plain track files 2006-11-16 16:38:23 +00:00
373e401671 Polished porting hints 2006-11-16 14:21:27 +00:00
06d008d6c6 Polished porting hints and self-compliance to newly established specs 2006-11-16 13:40:21 +00:00
11c9444b6c Made consolidaed operating system adapters for ease of porting 2006-11-16 11:18:44 +00:00
ff284b3f51 Made consolidaed operating system adapters for ease of porting 2006-11-16 11:17:55 +00:00
628e935fe5 Narrowed system specific part of enumerate_common() 2006-11-15 20:49:27 +00:00
13641fcbae Made portability clarifications 2006-11-15 17:10:12 +00:00
595b877a24 Adjusted some texts to new multi-session situation 2006-11-15 09:14:17 +00:00
17d1d2e8a6 Enhanced optional SCSI command logging 2006-11-15 09:11:57 +00:00
c1b3d3341e Prepared tests for eventual drive which might support SAO to appendable CD 2006-11-15 09:05:06 +00:00
725b6515ff Fixed a wrong name in API description 2006-11-14 16:38:01 +00:00
61a535f3ac Implemented try to find on restricted drives a suitable write mode as default 2006-11-14 10:41:06 +00:00
7c312a33d9 Corrected a typo reported by George Danchev 2006-11-14 08:33:34 +00:00
b7d369dbb6 Changed references to libisofs 2006-11-14 08:32:32 +00:00
16cbb18f15 Removed remaining signs of libisofs in libburn tree 2006-11-14 00:52:32 +00:00
4f83818ff8 Removed references to libisofs 2006-11-13 15:00:42 +00:00
9e383a3b9e Adjusted description of write mode default 2006-11-13 13:23:34 +00:00
a9b7d8250e Next cdrskin-0.2.5 cycle 2006-11-13 13:04:38 +00:00
1ec94d9226 Refered to both libburn and libisofs in SVN description, updated history 2006-11-13 11:58:57 +00:00
c1607eeac4 Changed SVN URLs to reflect new structure 2006-11-13 08:33:21 +00:00
8927e3df9f Started logical separation of libisofs and libburn 2006-11-13 00:13:21 +00:00
7458223cc0 Made -toc on blank CD exit with value 0 (rather than 7 with no media) 2006-11-12 18:51:59 +00:00
5a0b597e3f Reacted on error condition during write operation 2006-11-12 15:28:09 +00:00
bf20758906 Made SAO preferrable default write mode, kept TAO as default where needed 2006-11-12 11:34:58 +00:00
1bfd7b5a5f Made speed 0 in burn_drive_set_speed() really maximum speed (i.e. FFFFh) 2006-11-12 08:56:46 +00:00
aa813303a4 Updated docs about multi-session 2006-11-11 16:33:23 +00:00
9baf20e907 Prepared next cdrskin-0.2.5 cycle 2006-11-11 16:12:52 +00:00
1947c3a25d Generally enabled -multi, -msinfo and writing to appendable CDs in TAO mode 2006-11-11 15:27:40 +00:00
6b22dadcdd Demanded (for now) -tao for writing to appendable CDs 2006-11-11 15:19:08 +00:00
4efccd15b3 Implemented handling of unsuitable disk states with -msinfo 2006-11-11 13:46:22 +00:00
496fb67c29 Reacted on some warnings of gcc -O2 2006-11-11 12:39:49 +00:00
bc97bdfa71 Reacted on some warnings of gcc -O2 2006-11-11 12:39:08 +00:00
68784d8703 Implemented not so provisory -msinfo 2006-11-11 12:31:13 +00:00
10c01ebc83 Implemented not so provisory -msinfo 2006-11-11 12:27:43 +00:00
6c22b98235 New API function burn_disc_track_lba_nwa() 2006-11-11 12:22:53 +00:00
62bd5963d0 Read -msinfo from first track of last session and not from last track 2006-11-10 18:50:56 +00:00
726cd2664d Made it work with fifos and other non-plain files as track sources 2006-11-10 18:39:35 +00:00
5378638ba7 Provisory -msinfo (very verbous on stderr) 2006-11-10 17:21:08 +00:00
347aa3fe0c Expressing more self-confidence 2006-11-10 09:37:48 +00:00
c9478cc15e Experimentally enabled burning to BURN_DISC_APPENDABLE (tested with TAO only) 2006-11-09 19:29:39 +00:00
ce0d783e82 Corrected first speed measurement report in TAO mode (which was random) 2006-11-09 15:13:33 +00:00
5057fe48ab Silenced SCSI error (debugging) messages about missing media 2006-11-09 11:36:38 +00:00
fcc755a5b8 Check desired write and block type with burn_drive_info.*_block_types 2006-11-09 11:27:51 +00:00
ab8127f980 Prepared next cdrskin-0.2.5 upload cycle 2006-11-08 18:08:03 +00:00
dad50348db Made track write counter of SAO count rather too much than too few bytes 2006-11-08 17:28:56 +00:00
140ff9ade4 Mentioned bug fix about trailing trash 2006-11-08 17:27:27 +00:00
2a64a0d3b1 Avoided error message and nonzero exit with trailing trash on .wav 2006-11-08 16:56:16 +00:00
82983cd7c1 Updated documentation about TAO 2006-11-07 15:22:06 +00:00
b31e882582 Updated documentation about TAO 2006-11-07 14:58:38 +00:00
dd80b2fc88 Prepared next cdrskin-0.2.5 upload cycle 2006-11-07 13:14:24 +00:00
3051fc1987 Made -tao default for single track or stdin, -sao for any other multi-track 2006-11-07 11:45:10 +00:00
e54be83b27 Cared for some SCSI error conditions which were ignored up to now 2006-11-06 19:58:24 +00:00
448aac8880 Made CD with unclosed track blankable (by -force) 2006-11-06 15:52:45 +00:00
db4522bbdc Make -toc on multiple sessions more compatible 2006-11-06 12:14:10 +00:00
d7c34f05e4 New API burn_write_opts_set_multi(). (But libburn cannot burn next session yet) 2006-11-06 11:42:21 +00:00
b96fbd5bd8 Adapted documentation to reflect experimental TAO mode 2006-11-06 08:34:21 +00:00
25d5a2afe4 Enabled audio tracks with TAO 2006-11-04 09:27:50 +00:00
66515523c1 Enabled TAO for multiple -data tracks (-audio still ends after 0 bytes) 2006-11-03 20:22:54 +00:00
684cfd0cd2 Installed decent abort behavior with TAO 2006-11-03 15:10:24 +00:00
a0e745c54a Removed some obsolete debugging messages 2006-11-03 06:31:51 +00:00
a239d54bd7 Changed status report during blanking (there are no "sectors") 2006-11-03 06:30:18 +00:00
c98dd9b0a7 Installed status communications about closing session ("Fixating") 2006-11-02 21:17:32 +00:00
193d674852 Mentioned -tao and experimental compile 2006-11-02 12:21:14 +00:00
15e37555ae Repaired broken macro settings during Linux build 2006-11-01 17:19:37 +00:00
d337722920 dapted cdrskin pacifier to possibly unknown track size 2006-11-01 16:39:07 +00:00
5af92d13fe Made single track TAO work without fixed size (compile -experimental) 2006-10-31 18:48:18 +00:00
114307a679 Made single track TAO work (sector i/o still wants fixed size, though) 2006-10-31 11:55:51 +00:00
99ca953b1d Made MMC command CLOSE TRACK/SESSION available to struct burn_drive 2006-10-30 11:18:36 +00:00
b837cc134d Deleted from to EXTRA_DIST libburn/sg-*.h 2006-10-29 08:17:49 +00:00
d3ee0b72e4 Added to EXTRA_DIST libburn/sg-*.[ch] 2006-10-29 08:13:01 +00:00
6914e2f7e2 Added to EXTRA_DIST cdrskin/cleanup.[ch] 2006-10-29 07:47:24 +00:00
37017119b0 Copied missing file from libburn-0.2.2 2006-10-29 07:26:35 +00:00
447d2365c7 Corrected bug which made every track from file an audio track 2006-10-28 15:27:30 +00:00
ece61a1860 Corrected misnaming of my development directory 2006-10-28 12:49:28 +00:00
acc6bdd95c Performed cdrskin version leap to cdrskin-0.2.5 2006-10-28 12:31:46 +00:00
559811e8ef Performed cdrskin version leap to cdrskin-0.2.5 2006-10-28 11:52:49 +00:00
125 changed files with 35433 additions and 8309 deletions

View File

@ -1,5 +1,3 @@
Developers:
Mario Danic
Thomas Schmitt
Lorenzo Taylor

6
CONTRIBUTORS Normal file
View File

@ -0,0 +1,6 @@
Joe Neeman
Philippe Rouquier
Gabriel Craciunescu
George Danchev
Jean-Francois Wauthy
Lorenzo Taylor

View File

@ -1,13 +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 Mario Danic, Thomas Schmitt
Copyright (C) 2006-2009 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 as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
it under the terms of the GNU General Public License version 2 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

1
ChangeLog Normal file
View File

@ -0,0 +1 @@
nothing here now

234
INSTALL Normal file
View File

@ -0,0 +1,234 @@
Installation Instructions
*************************
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
2006 Free Software Foundation, Inc.
This file is free documentation; the Free Software Foundation gives
unlimited permission to copy, distribute and modify it.
Basic Installation
==================
Briefly, the shell commands `./configure; make; make install' should
configure, build, and install this package. The following
more-detailed instructions are generic; see the `README' file for
instructions specific to this package.
The `configure' shell script attempts to guess correct values for
various system-dependent variables used during compilation. It uses
those values to create a `Makefile' in each directory of the package.
It may also create one or more `.h' files containing system-dependent
definitions. Finally, it creates a shell script `config.status' that
you can run in the future to recreate the current configuration, and a
file `config.log' containing compiler output (useful mainly for
debugging `configure').
It can also use an optional file (typically called `config.cache'
and enabled with `--cache-file=config.cache' or simply `-C') that saves
the results of its tests to speed up reconfiguring. Caching is
disabled by default to prevent problems with accidental use of stale
cache files.
If you need to do unusual things to compile the package, please try
to figure out how `configure' could check whether to do them, and mail
diffs or instructions to the address given in the `README' so they can
be considered for the next release. If you are using the cache, and at
some point `config.cache' contains results you don't want to keep, you
may remove or edit it.
The file `configure.ac' (or `configure.in') is used to create
`configure' by a program called `autoconf'. You need `configure.ac' if
you want to change it or regenerate `configure' using a newer version
of `autoconf'.
The simplest way to compile this package is:
1. `cd' to the directory containing the package's source code and type
`./configure' to configure the package for your system.
Running `configure' might take a while. While running, it prints
some messages telling which features it is checking for.
2. Type `make' to compile the package.
3. Optionally, type `make check' to run any self-tests that come with
the package.
4. Type `make install' to install the programs and any data files and
documentation.
5. You can remove the program binaries and object files from the
source code directory by typing `make clean'. To also remove the
files that `configure' created (so you can compile the package for
a different kind of computer), type `make distclean'. There is
also a `make maintainer-clean' target, but that is intended mainly
for the package's developers. If you use it, you may have to get
all sorts of other programs in order to regenerate files that came
with the distribution.
Compilers and Options
=====================
Some systems require unusual options for compilation or linking that the
`configure' script does not know about. Run `./configure --help' for
details on some of the pertinent environment variables.
You can give `configure' initial values for configuration parameters
by setting variables in the command line or in the environment. Here
is an example:
./configure CC=c99 CFLAGS=-g LIBS=-lposix
*Note Defining Variables::, for more details.
Compiling For Multiple Architectures
====================================
You can compile the package for more than one kind of computer at the
same time, by placing the object files for each architecture in their
own directory. To do this, you can use GNU `make'. `cd' to the
directory where you want the object files and executables to go and run
the `configure' script. `configure' automatically checks for the
source code in the directory that `configure' is in and in `..'.
With a non-GNU `make', it is safer to compile the package for one
architecture at a time in the source code directory. After you have
installed the package for one architecture, use `make distclean' before
reconfiguring for another architecture.
Installation Names
==================
By default, `make install' installs the package's commands under
`/usr/local/bin', include files under `/usr/local/include', etc. You
can specify an installation prefix other than `/usr/local' by giving
`configure' the option `--prefix=PREFIX'.
You can specify separate installation prefixes for
architecture-specific files and architecture-independent files. If you
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
PREFIX as the prefix for installing programs and libraries.
Documentation and other data files still use the regular prefix.
In addition, if you use an unusual directory layout you can give
options like `--bindir=DIR' to specify different values for particular
kinds of files. Run `configure --help' for a list of the directories
you can set and what kinds of files go in them.
If the package supports it, you can cause programs to be installed
with an extra prefix or suffix on their names by giving `configure' the
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
Optional Features
=================
Some packages pay attention to `--enable-FEATURE' options to
`configure', where FEATURE indicates an optional part of the package.
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
is something like `gnu-as' or `x' (for the X Window System). The
`README' should mention any `--enable-' and `--with-' options that the
package recognizes.
For packages that use the X Window System, `configure' can usually
find the X include and library files automatically, but if it doesn't,
you can use the `configure' options `--x-includes=DIR' and
`--x-libraries=DIR' to specify their locations.
Specifying the System Type
==========================
There may be some features `configure' cannot figure out automatically,
but needs to determine by the type of machine the package will run on.
Usually, assuming the package is built to be run on the _same_
architectures, `configure' can figure that out, but if it prints a
message saying it cannot guess the machine type, give it the
`--build=TYPE' option. TYPE can either be a short name for the system
type, such as `sun4', or a canonical name which has the form:
CPU-COMPANY-SYSTEM
where SYSTEM can have one of these forms:
OS KERNEL-OS
See the file `config.sub' for the possible values of each field. If
`config.sub' isn't included in this package, then this package doesn't
need to know the machine type.
If you are _building_ compiler tools for cross-compiling, you should
use the option `--target=TYPE' to select the type of system they will
produce code for.
If you want to _use_ a cross compiler, that generates code for a
platform different from the build platform, you should specify the
"host" platform (i.e., that on which the generated programs will
eventually be run) with `--host=TYPE'.
Sharing Defaults
================
If you want to set default values for `configure' scripts to share, you
can create a site shell script called `config.site' that gives default
values for variables like `CC', `cache_file', and `prefix'.
`configure' looks for `PREFIX/share/config.site' if it exists, then
`PREFIX/etc/config.site' if it exists. Or, you can set the
`CONFIG_SITE' environment variable to the location of the site script.
A warning: not all `configure' scripts look for a site script.
Defining Variables
==================
Variables not defined in a site shell script can be set in the
environment passed to `configure'. However, some packages may run
configure again during the build, and the customized values of these
variables may be lost. In order to avoid this problem, you should set
them in the `configure' command line, using `VAR=value'. For example:
./configure CC=/usr/local2/bin/gcc
causes the specified `gcc' to be used as the C compiler (unless it is
overridden in the site shell script).
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
an Autoconf bug. Until the bug is fixed you can use this workaround:
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
`configure' Invocation
======================
`configure' recognizes the following options to control how it operates.
`--help'
`-h'
Print a summary of the options to `configure', and exit.
`--version'
`-V'
Print the version of Autoconf used to generate the `configure'
script, and exit.
`--cache-file=FILE'
Enable the cache: use and save the results of the tests in FILE,
traditionally `config.cache'. FILE defaults to `/dev/null' to
disable caching.
`--config-cache'
`-C'
Alias for `--cache-file=config.cache'.
`--quiet'
`--silent'
`-q'
Do not print messages saying which checks are being made. To
suppress all normal output, redirect it to `/dev/null' (any error
messages will still be shown).
`--srcdir=DIR'
Look for the package's source code in directory DIR. Usually
`configure' can determine that directory automatically.
`configure' also accepts some other, not widely useful, options. Run
`configure --help' for more details.

View File

@ -1,7 +1,7 @@
pkgconfigdir=$(libdir)/pkgconfig
libincludedir=$(includedir)/libburn
lib_LTLIBRARIES = libburn/libburn.la libisofs/libisofs.la
lib_LTLIBRARIES = libburn/libburn.la
## ========================================================================= ##
@ -39,6 +39,7 @@ libburn_libburn_la_SOURCES = \
libburn/null.h \
libburn/options.c \
libburn/options.h \
libburn/os.h \
libburn/read.c \
libburn/read.h \
libburn/sbc.c \
@ -64,44 +65,18 @@ libburn_libburn_la_SOURCES = \
## libburn/sg-@ARCH@.c \
libisofs_libisofs_la_LDFLAGS = \
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
libisofs_libisofs_la_SOURCES = \
libisofs/tree.h \
libisofs/tree.c \
libisofs/volume.h \
libisofs/volume.c \
libisofs/util.h \
libisofs/util.c \
libisofs/ecma119.c \
libisofs/ecma119.h \
libisofs/ecma119_tree.c \
libisofs/ecma119_tree.h \
libisofs/susp.h \
libisofs/susp.c \
libisofs/rockridge.h \
libisofs/rockridge.c \
libisofs/joliet.c \
libisofs/joliet.h \
libisofs/exclude.c \
libisofs/exclude.h \
libisofs/hash.h \
libisofs/hash.c
libinclude_HEADERS = \
libburn/libburn.h \
libisofs/libisofs.h
libburn/libburn.h
## ========================================================================= ##
## Build test applications
noinst_PROGRAMS = \
test/libburner \
test/telltoc \
test/dewav \
test/fake_au \
test/iso \
test/poll \
test/toc \
test/structest
bin_PROGRAMS = \
@ -110,6 +85,9 @@ bin_PROGRAMS = \
test_libburner_CPPFLAGS = -Ilibburn
test_libburner_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
test_libburner_SOURCES = test/libburner.c
test_telltoc_CPPFLAGS = -Ilibburn
test_telltoc_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
test_telltoc_SOURCES = test/telltoc.c
test_dewav_CPPFLAGS = -Ilibburn
test_dewav_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
test_dewav_SOURCES = test/dewav.c
@ -119,22 +97,19 @@ test_fake_au_SOURCES = test/fake_au.c
test_poll_CPPFLAGS = -Ilibburn
test_poll_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
test_poll_SOURCES = test/poll.c
test_toc_CPPFLAGS = -Ilibburn
test_toc_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
test_toc_SOURCES = test/toc.c
test_structest_CPPFLAGS = -Ilibburn
test_structest_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
test_structest_SOURCES = test/structest.c
test_iso_CPPFLAGS = -Ilibisofs
test_iso_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS)
test_iso_SOURCES = test/iso.c
## cdrskin construction site - ts A60816
## cdrskin construction site - ts A60816 - A90102
cdrskin_cdrskin_CPPFLAGS = -Ilibburn
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_0_2_3
cdrskin_cdrskin_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_0_6_0
# cdrskin_cdrskin_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
# ts A80123, change proposed by Simon Huggins to cause dynamic libburn linking
cdrskin_cdrskin_LDADD = libburn/libburn.la $(THREAD_LIBS)
cdrskin_cdrskin_SOURCES = cdrskin/cdrskin.c cdrskin/cdrfifo.c cdrskin/cdrfifo.h cdrskin/cdrskin_timestamp.h
## cdrskin_cdrskin_SOURCES = cdrskin/cdrskin.c cdrskin/cdrfifo.c cdrskin/cdrfifo.h cdrskin/cleanup.c cdrskin/cleanup.h cdrskin/cdrskin_timestamp.h
##
## Open questions: how to compute $timestamp and express -DX="$timestamp"
##
@ -174,13 +149,9 @@ uninstall-local:
# Indent source files
indent_files = \
$(libisofs_libisofs_la_SOURCES) \
$(libburn_libburn_la_SOURCES) \
$(test_libburner_SOURCES) \
$(test_poll_SOURCES) \
$(test_toc_SOURCES) \
$(test_structest_SOURCES) \
$(test_iso_SOURCES)
$(test_structest_SOURCES)
indent: $(indent_files)
@ -196,12 +167,13 @@ indent: $(indent_files)
# Extra things
nodist_pkgconfig_DATA = \
libburn-1.pc \
libisofs-1.pc
libburn-1.pc
# http://www.nada.kth.se/cgi-bin/info?(automake.info)Man%20pages
man_MANS = cdrskin/cdrskin.1
EXTRA_DIST = \
libburn-1.pc.in \
libisofs-1.pc.in \
version.h.in \
doc/comments \
doc/doxygen.conf.in \
@ -212,8 +184,19 @@ EXTRA_DIST = \
cdrskin/README \
cdrskin/cdrecord_spy.sh \
cdrskin/compile_cdrskin.sh \
cdrskin/convert_man_to_html.sh \
cdrskin/changelog.txt \
cdrskin/cdrskin_eng.html \
cdrskin/wiki_plain.txt \
COPYING
cdrskin/cleanup.h \
cdrskin/cleanup.c \
libburn/os-freebsd.h \
libburn/os-linux.h \
libburn/sg-freebsd.c \
libburn/sg-linux.c \
COPYING \
NEWS \
ChangeLog \
INSTALL \
$(man_MANS)

1
NEWS Normal file
View File

@ -0,0 +1 @@
nothing here now

307
README
View File

@ -1,97 +1,157 @@
------------------------------------------------------------------------------
libburn.pykix.org
libburnia-project.org
------------------------------------------------------------------------------
This all is under GPL.
(See GPL reference, our clarification and commitment at the end of this text)
------------------------------------------------------------------------------
libburn.pykix.org
libburn-project.org
By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
Copyright (C) 2006 Mario Danic, Thomas Schmitt
Still containing parts of
Libburn. By Derek Foreman <derek@signalmarketing.com> and
Ben Jansens <xor@orodu.net>
Copyright (C) 2006-2009 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 libburn.pykix.org-copyright
holders and then libburn.pykix.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 libburn.pykix.org toplevel README (C) 2006 Thomas Schmitt
http://files.libburnia-project.org/releases/libburn-0.6.0.pl01.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://libburn-svn.pykix.org/trunk libburn_pykix
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.6.0.pl01.tar.gz, take it to a directory of your choice and do:
To build libburn.pykix.org and its subprojects it should be sufficient to go
into its toplevel directory (here: "libburn_pykix") and execute
./configure
tar xzf libburn-0.6.0.pl01.tar.gz
cd libburn-0.6.0
./configure --prefix=/usr
make
To make the libraries accessible for running resp. developing applications
To make libburn accessible for running resp. application development,
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.
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-0.5.9
cd libburn-0.5.9
./bootstrap
./configure --prefix=/usr
make
make install
Warning: The trunk might contain experimental features which might not
persist until next release.
------------------------------------------------------------------------------
Overview of libburn.pykix.org
An important part of the project, libisofs, is hosted in a bzr repository at
launchpad.net :
bzr branch lp:libisofs
libburn.pykix.org is an open-source library for reading, mastering and writing
optical discs. For now this means only CD-R and CD-RW.
Another part the project, libisoburn, is hosted in the libburnia SVN, too:
svn co http://svn.libburnia-project.org/libisoburn/trunk libisoburn
See README files there.
------------------------------------------------------------------------------
Overview of libburnia-project.org
libburnia-project.org is an open-source software project for reading, mastering
and writing optical discs.
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 Linux with kernels >= 2.4 and on FreeBSD versions
with ATAPI/CAM support enabled in the kernel, see atapicam(4).
Our scope is currently Linux 2.4 and 2.6 and we will have a hard time to widen
this for now, because of our history. The project could need advise from or
membership of skilled kernel people and people who know how to talk CD/DVD
drives into doing things.
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.
We do have a workable code base for burning data CDs, though. The burn API is
quite comprehensively documented and can be used to build a presentable
application.
We do have a functional binary which emulates parts 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
makes possible a single binary application which covers all steps of image
composition, updating and writing. Quite unique in the Linux world.
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/hdX (e.g. on kernel 2.6).
libburn is the foundation of our cdrecord emulation.
/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
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.
the services traditionally provided by cdrecord. Additionally it
provides libburn's DVD 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.
- test is a collection of application gestures and examples given by the
authors of the library features. The main API example for libburn
is test/libburner.c .
- 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 deleting, renaming, attribute
changing, incremental backups, activating boot images, and
extracting of files from ISO images to disk.
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 plan to be a responsive upstream. Bear with us. We are still practicing.
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:
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).
------------------------------------------------------------------------------
@ -114,13 +174,13 @@ Project history as far as known to me:
It has meanwhile moved to use vanilla libburn.pykix.org , though.
Version 0.1.4 constitutes the first release of this kind.
- In Juli 2006 our team mate Mario Danic announced a revival of libburn
- In July 2006 our team mate Mario Danic announced a revival of libburn
which by about nearly everybody else was perceived as unfriendly fork.
Derek Foreman four days later posted a message which expressed his
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
@ -152,12 +212,151 @@ Project history as far as known to me:
- 16th September 2006 feature freeze for release of libburn-0.2.2 .
- 20th September 2006 release of libburn-0.2.2 .
- 26th October 2006 feature freeze for cdrskin-0.2.4 based on libburn-0.2.3 .
This version of cdrskin is much more cdrecord compatible in repect
to drive addressing and audio features.
- 30th October 2006 release of cdrskin-0.2.4 .
- 13th November 2006 splitting releases of libburn+cdrskin from libisofs.
- 24th November 2006 release of libburn-0.2.6 and cdrskin-0.2.6 . cdrskin has
become suitable for unaware frontends as long as they perform only the core
of cdrecord use cases (including open-ended input streams, audio, and
multi-session).
- 28th November 2006 the umbrella project which encloses both, libisofs and
libburn, is now called libburnia. For the origin of this name, see
http://en.wikipedia.org/wiki/Liburnians .
- 16th January 2007 release of libburn-0.3.0 and cdrskin-0.3.0 . Now the scope
is widened to a first class of DVD media: overwriteable single layer types
DVD-RAM, DVD+RW, DVD-RW. This is not a cdrecord emulation but rather inspired
by dvd+rw-tools' "poor man" writing facility for this class of media.
Taking a bow towards Andy Polyakov.
- 11th February 2007 version 0.3.2 covers sequential DVD-RW and DVD-R with
multi-session and with DAO.
- 12th March 2007 version 0.3.4 supports DVD+R and thus covers all single layer
DVD media. Code for double layer DVD+/-R is implemented but awaits a tester
yet.
- 23th April 2007 version 0.3.6 follows the unanimous opinion of Linux kernel
people that one should not use /dev/sg on kernel 2.6.
- 31st July 2007 version 0.3.8 marks the first anniversary of libburn revival.
We look back on improved stability, a substantially extended list of media
and write modes, and better protection against typical user mishaps.
- 24th October 2007 version 0.4.0 is the foundation of new library libisoburn
and an upcomming integrated application for manipulating and writing
ISO 9660 + Rock Ridge images. cdrskin-0.4.0 got capabilities like growisofs
by these enhancements: growing of overwriteable media and disk files.
Taking again a bow towards Andy Polyakov.
- 26th Januar 2008 version 0.4.2 rectifies the version numbering so that we
reliably release libburn.so.4 as should have been done since libburn-0.3.2.
cdrskin now is by default linked dynamically and does a runtime check
to ensure not to be started with a libburn which is older than itself.
- 3rd Feb 2008 libisofs-0.2.x (.so.5) has been deprecated.
- 14th Feb 2008 libisofs-0.6.2 permanently replaces the old libisofs-0.2.x.
It is the first release of new libisofs.so.6 which will guarantee future
API/ABI compatibility for its whole feature set.
- 15th Feb 2008 libisoburn-0.1.0 (.so.1) coordinates libisofs and libburn for
the purpose of ISO image reading and writing. It emulates multi-session on
overwriteable media. Application xorriso makes use of all three libraries.
- 8th Apr 2008 libburn-0.4.4 has proven to be capable of burning to DVD+R/DL
and read performance on disk file pseudo-drives has been improved.
- 27th Apr 2008 libisofs-0.6.4 can now read data file content from images
and can map pieces of disk files onto image files. Image directory iteration
has been enhanced. Input data streams and extended information have been
exposed in the API to allow future development.
- 29th Apr 2008 libisoburn-0.1.4 was made more efficient with reading of
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 cdrecord and mkisofs is
provided.
- 10th May 2008 libburn-0.4.6 supports formatting and writing of BD-RE,
full nominal speed for DVD-RAM and BD-RE. cdrskin has a unified blank
type with automatic media state recognition.
- 17th May 2008 an old bug with DVD-RAM and now with BD-RE is fixed by
libburn-0.4.8 to allow libisoburn emulation of multisession on those media.
- 19th May 2008 libisoburn-0.1.6 brings better table-of-content emulation
on overwriteble media and disk files.
- 1st Jun 2008 libisofs-0.6.6 fixes some problems around device files.
- 3rd Jun 2008 libisoburn-0.1.8 fixes a bug with overwriteable media.
- 23rd Jun 2008 libisoburn-0.2.0 introduces extraction of files from
ISO images.
- 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.
------------------------------------------------------------------------------
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; either version 2 of the License, or
(at your option) any later version.
the Free Software Foundation. To be exact: version 2 of that License.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
@ -170,9 +369,9 @@ Project history as far as known to me:
------------------------------------------------------------------------------
Clarification in my name and in the name of Mario Danic, upcoming copyright
holders on toplevel of libburn. To be fully in effect after the remaining other
copyrighted code has been replaced by ours and by copyright-free contributions
of our friends:
holders 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

View File

@ -3,5 +3,8 @@
aclocal
libtoolize --copy --force
autoconf
autoheader
# ts A61101 : libburn is not prepared for config.h
# autoheader
automake --foreign --add-missing --copy --include-deps

View File

@ -1,84 +1,37 @@
------------------------------------------------------------------------------
libburn.pykix.org scdbackup.sourceforge.net/cdrskin_eng.html
libburnia-project.org scdbackup.sourceforge.net/cdrskin_eng.html
------------------------------------------------------------------------------
Installation instructions at about line 60. First the legal stuff:
------------------------------------------------------------------------------
This all is under GPL.
(See GPL reference, our clarification and commitment at the end of this text)
------------------------------------------------------------------------------
Based on and sub project of:
libburn.pykix.org
By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
Copyright (C) 2006 Mario Danic, Thomas Schmitt
libburn.pykix.org is inspired by and in other components 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
See toplevel README for an overview of the current copyright situation in
libburn.pykix.org.
------------------------------------------------------------------------------
My thanks to the above authors (except myself, of course) for making the
following possible.
cdrskin. By Thomas Schmitt <scdbackup@gmx.net>
Integrated sub project of libburn.pykix.org but also published via:
Integrated sub project of libburnia-project.org but also published via:
http://scdbackup.sourceforge.net/cdrskin_eng.html
http://scdbackup.sourceforge.net/cdrskin-0.2.3.tar.gz
Copyright (C) 2006 Thomas Schmitt
http://scdbackup.sourceforge.net/cdrskin-0.6.0.pl01.tar.gz
Copyright (C) 2006-2009 Thomas Schmitt, provided under GPL version 2.
------------------------------------------------------------------------------
On top of libburn there is implemented cdrskin 0.2.3, a limited cdrecord
compatibility wrapper which allows to use some libburn features from
the command line.
Interested users of cdrecord are invited to participate in the development
of cdrskin. Contact: scdbackup@gmx.net or libburn-hackers@pykix.org .
We will keep copyright narrow but will of course acknowledge valuable
contributions in a due way.
cdrskin is a limited cdrecord compatibility wrapper which allows to use
most of the libburn features from the command line.
Important :
This software is provided as is. There is no warranty implied and no
protection against possible damages. You use this on your own risk.
Don't blame me or other authors of libburn if anything goes wrong.
Currently it is supported on Linux with kernels >= 2.4 and on FreeBSD versions
with ATAPI/CAM support enabled in the kernel, see atapicam(4).
I used it on my own risk with :
SuSE 7.2, kernel 2.4.4, ide-scsi emulation, LITE-ON LTR48125S CD burner, 2002
SuSE 9.0, kernel 2.4.21, ide-scsi emulation, LG GSA-4082B CD/DVD burner, 2004
NEC ND-4570A CD/DVD burner, 2006
RIP-14.4, kernel 2.6.14, no ide-scsi, with all above burners
It fails to compile or run on SuSE 6.4 (kernel 2.2.14).
It does not find the IDE CD burner on SuSE 7.2 without ide-scsi.
Other people sucessfully tested cdrskin on several kernel 2.6 based x86 Linux
systems, including 64 bit systems. (Further reports are welcome.)
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 ..."
Compilation, First Glimpse, Installation
Obtain cdrskin-0.2.3.tar.gz , take it to a directory of your choice and do:
Obtain cdrskin-0.6.0.pl01.tar.gz, take it to a directory of your choice and do:
tar xzf cdrskin-0.2.3.tar.gz
cd cdrskin-0.2.3
tar xzf cdrskin-0.6.0.pl01.tar.gz
cd cdrskin-0.6.0
Or obtain a libburn.pykix.org SVN snapshot,
go into the toplevel directory of the snapshot (e.g. cd libburn_pykix ),
and execute the autotools script ./bootstrap . Use autools version >= 1.7 .
Within that directory execute:
Within that toplevel directory of either cdrskin-0.2.3 or libburn then execute:
./configure
./configure --prefix=/usr
make
(Note: there are next-level directories "libburn" and "cdrskin". Those
would be the wrong ones. Meant is the highest directory of tarball resp.
SVN download. Among others containing files "AUTHORS", "configure",
"Makefile.am", as well as directories "libburn" and "cdrskin".)
This will already produce a cdrskin binary. But it might be necessary to
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.
@ -86,16 +39,27 @@ In order to surely get a standalone binary, execute
cdrskin/compile_cdrskin.sh
Version identification an help texts available afterwards:
Version identification and help texts available afterwards:
cdrskin/cdrskin -version
cdrskin/cdrskin --help
cdrskin/cdrskin -help
man cdrskin/cdrskin.1
Install (eventually as superuser) cdrskin to a directory where it can be found:
The command for global installation of both, libburn and cdrskin is
make install
If the library libburn.so.4 is not found with a test run of cdrskin, then
try whether command
ldconfig
makes it accessible. With the statically linked binary this should not matter.
With that static binary you may as well do the few necessary actions manually.
If cdrskin was already installed by a previous version, or by "make install"
in the course of this installation, then find out where:
which cdrskin
Copy your standalone binary to exactly the address which you get as reply
Copy your standalone binary to exactly the address which you get as reply.
E.g.:
cp cdrskin/cdrskin /usr/bin/cdrskin
@ -108,6 +72,14 @@ 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.)
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:
cp cdrskin/cdrskin.1 /usr/share/man/man1/cdrskin.1
Note: The content of the cdrskin tarball is essentially the complete libburn
of the same version number. You may thus perform above steps in a local
SVN copy of libburn or in a unpacked libburn tarball as well.
Usage
@ -121,58 +93,81 @@ The superuser should be able to see any usable drive and then set the
permissions as needed. If this hangs then there is a drive with
unexpected problems (locked, busy, broken, whatever). You might have to
guess the address of your (non-broken) burner by other means, then.
On Linux 2.4 this would be some /dev/sgN and on 2.6. some /dev/hdX.
On Linux 2.4 this would be some /dev/sgN and on 2.6. some /dev/srM or /dev/hdX.
The output of cdrskin --devices might look like
0 dev='/dev/sg0' rwrwr- : '_NEC' 'DVD_RW ND-4570A'
1 dev='/dev/sg1' rwrw-- : 'HL-DT-ST' 'DVDRAM GSA-4082B'
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/sg0 /dev/sg1
chmod a+rw /dev/sr0 /dev/sr1
This is equivalent to the traditional setup chmod a+x,u+s cdrecord.
I strongly discourage to run cdrskin with setuid root or via sudo !
It is not checked for the necessary degree of hacker safety.
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
which are not listed by option --devices but point to the same SCSI addresses
as listed device files. This addressing via e.g. /dev/sr0 or /dev/scd1 is
compatible with generic read programs like dd and with write program growisofs.
For finding /dev/sg1 from /dev/sr0, the program needs rw-access to both files.
Usage examples
For options and recordable media classes see
man 1 cdrskin
Get an overview of cdrecord style addresses of available devices
cdrskin -scanbus
cdrskin dev=ATA -scanbus
cdrskin --devices
Note: Adresses reported with dev=ATA are to be used with prefix "ATA:". You may
well use device file addresses as reported with --devices. Examples:
dev=0,1,0 dev=/dev/sg1 dev=ATA:1,0,0 dev=/dev/hdc
See also "Drive Addressing".
Note: Address numbers have changed since cdrskin-0.2.2 in order to become
compatible with cdrecord numbers. To get the old number scheme, use
option --old_pseudo_scsi_adr . See also "Pseudo-SCSI Adresses".
Sorry for any inconvenience.
Adresses reported with dev=ATA need prefix "ATA:". Address examples:
dev=0,1,0 dev=ATA:1,0,0 dev=/dev/sg1 dev=/dev/hdc dev=/dev/sr0
See also "Drive Addressing" below.
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
cdrskin dev=0,1,0 -atip -v
Thoroughly blank a CD-RW
cdrskin -v dev=0,1,0 blank=all -eject
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
Blank CD-RW sufficiently for making it ready for overwrite
cdrskin -v dev=0,1,0 blank=fast -eject
Format DVD-RW to avoid need for blanking before re-use
cdrskin -v dev=0,1,0 blank=format_overwrite
Burn image file my_image.iso to CD
cdrskin -v dev=0,1,0 speed=12 fs=8m -sao driveropts=burnfree padsize=300k \
De-format DVD-RW to make it capable of multi-session again
cdrskin -v dev=/dev/sr0 blank=deformat_sequential
Burn image file my_image.iso to media
cdrskin -v dev=0,1,0 speed=12 fs=8m driveropts=burnfree padsize=300k \
-eject my_image.iso
Burn a compressed afio archive to CD on-the-fly
find . | afio -oZ - | cdrskin -v dev=0,1,0 fs=32m speed=8 -sao \
driveropts=burnfree padsize=300k tsize=650m -
Write multi-session to the same CD , DVD-R[W] or DVD+R[/DL]
cdrskin dev=/dev/hdc padsize=300k -multi 1.iso
cdrskin dev=/dev/hdc padsize=300k -multi 2.iso
cdrskin dev=/dev/hdc padsize=300k -multi 3.iso
cdrskin dev=/dev/hdc padsize=300k 4.iso
Burn 6 audio tracks from files with different formats to CD.
Get multi-session info for option -C of program mkisofs:
c_values=$(cdrskin dev=/dev/hdc -msinfo 2>/dev/null)
mkisofs ... -C "$c_values" ...
Burn a compressed afio archive to media on-the-fly
find . | afio -oZ - | cdrskin -v dev=0,1,0 fs=32m speed=8 \
driveropts=burnfree padsize=300k -
Burn 6 audio tracks from files with different formats to CD (not to any DVD).
Anything except .wav or .au files has to be converted into raw format first.
See below "Audio CD" for specifications.
ogg123 -d raw -f track01.cd /path/to/track1.ogg
@ -181,151 +176,51 @@ See below "Audio CD" for specifications.
madplay -o raw:track04.cd /path/to/track4.mp3
mppdec --raw-le /path/to/track5.mpc track05.cd
cdrskin dev=0,1,0 blank=fast -eject speed=48 \
cdrskin -v dev=0,1,0 blank=fast -eject speed=48 -sao \
-audio -swab track0[1-5].cd /path/to/track6.wav
Usage example with http://scdbackup.sourceforge.net
Address may be a cdrecord-style "scsibus,target,lun" as listed with
cdrskin -scanbus (and hopefully as listed with cdrecord -scanbus) :
export SCDBACKUP_SCSI_ADR="0,1,0"
or a device file address as listed by --devices with an accessible drive :
export SCDBACKUP_SCSI_ADR="/dev/sg1"
Set usage of cdrskin with appropriate options rather than cdrecord :
export SCDBACKUP_CDRECORD="cdrskin -v -v tao_to_sao_tsize=650m"
Run a backup :
scdbackup_home
Restrictions
The convenient burn mode TAO is not available with libburn yet.
Therefore it has to be defaulted to mode SAO which needs to know the track
size in advance. non-cdrecord option tao_to_sao_tsize=650m causes each CD
to get burned up to 650 MB regardless of the payload size.
Several advanced CD related options of cdrecord are still unsupported.
See output of command
cdrskin --list_ignored_options
If you have use cases for them, please report your wishes and expectations.
No multi session yet ... Please report your wishes.
On the other hand, the capability of multi-session and of writing streams
of unpredicted lenght surpass the current DVD capabilities of cdrecord.
Inspiration and Standard
cdrskin combines the command line interface standard set by cdrecord with
libburn, which is a control software for optical drives according to standard
MMC-5. For particular CD legacy commands, standards MMC-3 and MMC-1 apply.
For the original meaning of cdrecord options see :
man cdrecord
(http://cdrecord.berlios.de/old/private/man/cdrecord-2.0.html)
Do not bother Joerg Schilling with any cdrskin problems.
(Be cursed if you install cdrskin as "cdrecord" without clearly forwarding
this "don't bother Joerg" demand.)
this "don't bother Joerg" demand.)
cdrskin does not contain any bytes copied from cdrecord's sources. Many bytes
have been copied from the message output of cdrecord runs, though. I am
thankful to Joerg Schilling for every single one of them.
Actually i, Thomas Schmitt, am a devoted user of cdrecord via my project
scdbackup which still runs a bit better with cdrecord than with cdrskin. TAO.
I have the hope that Joerg feels more flattered than annoyed by cdrskin.
Drive Addressing
Drives get addressed either via their cdrecord-style addresses as listed
with option -scanbus (see below "Pseudo-SCSI Adresses") or via the paths
of device files.
Not only device files listed by --devices may be used but also device files
which via their major,minor numbers point to the same device driver as
a listed device file.
Helpful with Linux kernel 2.4 is a special SCSI feature:
It is possible to address a scsi(-emulated) drive via associated device files
which are not listed by option --devices but point to the same SCSI addresses
as listed device files. This addressing via e.g. /dev/sr0 or /dev/scd1 is
compatible with generic read programs like dd and with write program growisofs.
Pseudo-SCSI Adresses
cdrecord and cdrskin share the syntax of SCSI addresses but not necessarily
the meaning of the components. A cdrecord-style address for cdrskin
[prefix:]scsibus,target,lun
can be interpreted in two different modes.
Standard mode tries to be compatible to original cdrecord. This should be true
with (emulated) SCSI where the /dev/sgN with is looked up with matching
scsibus,target,lun as given by the operating system.
With dev=ATA: or dev=ATAPI: the translation to /dev/hdX is purely literal
but matches the cdrecord addresses on all systems tested so far:
X = 'a' + 2 * scsibus + target
where target only may have the values 0 or 1.
In this mode, option -scanbus will list only SCSI devices unless option
dev=ATA or dev=ATAPI are given, which will suppress SCSI devices and only
show IDE drives (i.e. /dev/hdX without ide-scsi emulation).
In mode --old_pseudo_scsi_adr there is a scsibus,target,lun representation
which has nothing to do with SCSI and thus is not compatible to cdrecord.
Each number triple corresponds either to a device file address or to a
libburn drive number.
Component "scsibus" indicates the translation method. Defined busses are:
0 target is the libburn drivenumber as listed with --devices
1 associated to device file /dev/sgN , target chooses N
2 associated to device file /dev/hdX , target 0='a', 1='b' ..., 25='z'
So "1,1,0" is /dev/sg1, "2,3,0" is /dev/hdd, "0,2,0" is libburn drive #2 at
some unspecified device file.
This scheme shall help to keep cdrecord-style addresses stable and exchangeable
between users without excluding drives with unexpected device addresses.
The numbering on bus 0 is prone to arbitrary changes caused by changes in
drive accessability.
Further busses may emerge as libburn evolves. "prefix" and "lun" may get
a meaning. To stay upward compatible, use addresses as printed by -scanbus.
User Defined Device Address Translation
Some programs or users have their own ideas about the address of their burner.
K3b 0.10 for example derives cdrecord addresses by own examination of the
devices and not by calling cdrecord -scanbus.
Standard mode will hopefully be fully compatible with their ideas.
Old frontends which do not know dev=ATA or dev=ATAPI and which do ask their
"cdrecord" via -scanbus may be well served with option --old_pseudo_scsi_adr .
To direct any remaining stubborn callers to the appropriate drives, cdrskin
allows to define device address aliases. Like
cdrskin dev_translation=+1,0,0+/dev/sg1 \
dev_translation=+ATA:1,0,0+/dev/sg1 \
dev_translation=-"cd+dvd"-0,1,0 \
...
Any of the addresses dev=1,0,0, dev=ATA:1,0,0, dev=cd+dvd will be mapped to
/dev/sg1 resp. to 0,1,0.
The first character after "dev_translation=" defines the character which
separates the two parts of the translation pair. (Above: "+" and "-".)
In K3b 0.10 it is possible to employ alternative writer programs by setting
their full path (e.g. /usr/bin/cdrskin) in menu
Settings:Configure K3b...:Programs:Search Path
and to make them default in menu
Settings:Configure K3b...:Programs:Programs:
A suitable setting for "cdrecord" in menu
Settings:Configure K3b...:Programs:User Parameters
would then probably be
-v dev_translation=+1,0,0+/dev/sg1
You will learn from button "Show Debugging Output" after a failed burn run
what cdrecord command was used with what address "dev=...". This address "..."
will be the right one to replace "1,0,0" in above example.
Many thanks to Andy Polyakov for his dvd+rw-tools
http://fy.chalmers.se/~appro/linux/DVD+RW/tools
which provide me with examples and pointers into MMC specs for DVD writing.
Startup Files
If not --no_rc is the first argument then cdrskin attempts on startup to read
arguments from the following three files:
/etc/defaults/cdrskin
/etc/default/cdrskin
/etc/opt/cdrskin/rc
/etc/cdrskin/cdrskin.conf
$HOME/.cdrskinrc
The files are read in the sequence given above.
Each readable line is treated as one single argument. No extra blanks.
@ -334,11 +229,9 @@ A first character '#' marks a comment, empty lines are ignored.
Example content of a startup file:
# This is the default device
dev=0,1,0
# To accomodate to eventual remnant cdrskin-0.2.2 addresses
dev_translation=+1,0,0+0,1,0
# Some more options
--fifo_start_empty
fifo_start_at=0
fs=16m
@ -368,6 +261,130 @@ I myself am not into audio. So libburn-hackers@pykix.org might be the
best address for suggestions, requests and bug reports.
DVD+RW , DVD-RAM , BD-RE
These random access media get treated as blank media regardless wether they
hold data or not. Options -audio and -multi are not allowed. Only one track
is allowed. -toc does not return information about the media content.
Speed is counted in DVD units (i.e. 1x = 1,385,000 bytes/second) or BD units
(1x = 4,495,625 bytes/second). Currently there is no difference between -sao
and -tao. If ever, then -tao will be the mode which preserves the current
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
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.
Option --grow_overwriteable_iso allows -multi (although unneeded), enables
-msinfo and -toc, and makes blank=fast an invalidator for ISO filesystems
on overwriteable media.
Initial session (equivalent to growisofs -Z):
mkisofs ... | cdrskin --grow_overwriteable_iso blank=fast ...
Add-on session (equivalent to growisofs -M):
cparms=$(cdrskin dev=/dev/sr0 --grow_overwriteable_iso -msinfo)
mkisofs -C "$cparms" -M /dev/sr0 ... | \
cdrskin dev=/dev/sr0 --grow_overwriteable_iso ... -
DVD-RW and DVD-R
DVD-RW are usable if formatted to state "Restricted Overwrite" or if in state
"Sequential Recording". DVD-R are always in sequential state.
"Sequential" is the state of unused media and of media previously blanked
or written by cdrecord. dvd+rw-format -blank can also achieve this state.
The according cdrskin option is blank=deformat_sequential .
If "Incremental Streaming" is available, then sequential media are capable
of multi-session like CD-R[W]. (But not capable of -audio recording.)
This means they need option -multi to stay appendable, need to be blanked
to be writeable from start, return useable info with -toc and -msinfo,
eventually perform appending automatically.
Without Incremental Streaming offered by the drive, only write mode DAO is
available with sequential DVD-R[W]. It only works with blank media, allows only
one single track, no -multi, and demands a fixely predicted track size.
(growisofs uses it with DVD-R[W] if option -dvd-compat is given.)
Overwriteable DVD-RW behave much like DVD+RW. "Restricted" refers only to the
granularity of random access and block size which have always to be aligned to
full 32 kB. Sequential DVD-RW are converted into overwriteable DVD-RW by
cdrskin dev=... -v blank=format_overwrite
(Command dvd+rw-format -force can achieve Restricted Overwrite, too.)
Formatting or first use of freshly formatted DVD-RW can produce unusual noises
from the drive and last several minutes. Depending on mutual compatibility of
drive and media, formatting can yield unusable media. It seems that those die
too on blanking by cdrecord, dvd+rw-format or cdrskin. Perils of DVD-RW.
There are three DVD-RW formatting variants with cdrskin currently:
blank=format_overwrite uses "DVD-RW Quick" formatting (MMC-type 15h)
and writes a first session of 128 MiB. This leads to media which are expandable
and random addressable by cdrskin.
blank=format_overwrite_quickest uses "DVD-RW Quick" formatting (type 15h) too,
but leaves the media in "intermediate" state. In the first session of writing
one may only write sequentially to such a DVD. After that, it gets random
addressable by cdrskin. DVD-ROM drives might show ill behavior with them.
blank=format_overwrite_full uses preferrably "Full Format" (type 00h).
This formatting lasts as long as writing a full DVD. It includes writing of
lead-out which is said to be good for DVD ROM compatibility.
De-formatting options are available to make overwriteable DVD-RW sequential:
blank=deformat_sequential performs thorough blanking of all states of DVD-RW.
blank=all and blank=fast perform the same thorough blanking, but refuse to do
this with overwriteable DVD-RW, thus preserving their formatting. The specs
allow minimal blanking but the resulting media on my drives offer no
Incremental Streaming afterwards. So blank=fast will do full blanking.
blank=deformat_sequential_quickest is faster but might yield DAO-only media.
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
cdrskin can use filesystem objects as emulated drives. Regular files or block
devices appear similar to DVD-RAM. Other file types resemble blank DVD-R.
Necessary precondition is option --allow_emulated_drives which is not accepted
if cdrskin took another user identity because of the setuid bit of its access
permissions.
Addresses of emulated drives begin with prefix "stdio:". E.g.
dev=stdio:/tmp/my_pseudo_drive
For safety reasons the superuser is only allowed to use /dev/null as emulated
drive. See man page section FILES for a way to lift that ban.
------------------------------------------------------------------------------
Special compilation variations
You may get a (super fat) statically linked binary by :
@ -385,12 +402,36 @@ 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.
------------------------------------------------------------------------------
Project aspects and legal stuff
------------------------------------------------------------------------------
Important Disclaimer :
This software is provided as is. There is no warranty implied and no
protection against possible damages. You use this on your own risk.
Don't blame me or other authors of libburn if anything goes wrong.
Actually, in case of severe trouble, nearly always the drive and the media
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 ...
------------------------------------------------------------------------------
Interested users are invited to participate in the development of cdrskin.
Contact: scdbackup@gmx.net or libburn-hackers@pykix.org .
We will keep copyright narrow but will of course acknowledge valuable
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 as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
it under the terms of the GNU General Public License version 2
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
@ -401,6 +442,21 @@ debugging messages.
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
------------------------------------------------------------------------------
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-2009 Mario Danic, Thomas Schmitt
libburnia-project.org is inspired by and in other components 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
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:

View File

@ -0,0 +1,244 @@
#!/bin/sh
set -x
# This script documents how this cdrskin version was derived from
# a vanilla libburn version. It is not intended nor needed for any
# use of cdrskin but included here only to show the technical
# relationship between both projects - which are close friends
# and issue roughly the same software.
#
# Package maintainers are advised to cover rather libburn than
# cdrskin unless they put only emphasis on the cdrecord emulation
# provided by cdrskin. libburn contains cdrskin - cdrskin is an
# oscillating, friendly and coordinated fork of libburn.
#
# Script results are a source tarball and two binaries
# one dynamic and one static in respect to system libs.
# Both binaries are static in respect to libburn.
#
# The script is to be run in the directory above the toplevel
# directory of libburn resp. cdrskin development.
#
# The top level directory in the SVN snapshot is named
intermediate="./libburn_pykix"
# libburn source used: http://libburnia.pykix.org
# Downloaded by:
# $ svn co http://libburnia-svn.pykix.org/libburn/tags/... $intermediate
# packed up in a tarball just to save it from inadverted changes by
# $ tar czf libburn_svn.tgz $intermediate
original="./libburn_svn_release.tgz"
# Historic moments:
# original="./libburn_svn_A60815.tgz"
# original="./libburn_cdrskin_A60819.tgz"
# My changes are in $changes , mainly in $changes/cdrskin
changes="./libburn-release"
skin_release="0.6.0"
patch_level=".pl00"
skin_rev="$skin_release""$patch_level"
# The result directory and the name of the result tarballs
target="./cdrskin-${skin_release}"
cdrskin_tarball="./cdrskin-${skin_rev}.tar.gz"
cdrskin_tarball_svn="./cdrskin-${skin_rev}.svn.tar.gz"
# (This once earned me an embarrassingly blooping source tarball)
# compile_dir="$changes"
compile_dir="$target"
compile_cmd="./cdrskin/compile_cdrskin.sh"
compile_static_opts="-static"
compile_result="cdrskin/cdrskin"
man_to_html_cmd="./cdrskin/convert_man_to_html.sh"
man_page_html="cdrskin/man_1_cdrskin.html"
# bintarget_dynamic="cdrskin_${skin_rev}-x86-suse9_0"
bintarget_dynamic="cdrskin_${skin_rev}-amd64-suse10_2"
bintarget_static="$bintarget_dynamic"-static
if test -d "$changes"
then
dummy=dummy
else
echo "$0 : FATAL : no directory $changes" >&2
exit 1
fi
for i in "$target" "$intermediate"
do
if test -e "$i"
then
echo "$0 : FATAL : already existing $i" >&2
exit 2
fi
done
if test -f "$original"
then
dummy=dummy
else
echo "$0 : FATAL : no file $original" >&2
exit 3
fi
# Unpack SVN snapshot.
tar xzf "$original"
# Rename the directory to the cdrskin name
mv "$intermediate" "$target"
# Copy the changes from the development tree
#
cdrskin_dir="$changes"/cdrskin
libburn_dir="$changes"/libburn
cdrskin_target="$target"/cdrskin
libburn_target="$target"/libburn
# Create version timestamp
# timestamp="$(date -u '+%Y.%m.%d.%H%M%S')"
# echo "$timestamp"
# echo '#define Cdrskin_timestamP "'"$timestamp"'"' >"$cdrskin_dir"/cdrskin_timestamp.h
# Add the cdrskin files
if test -e "$cdrskin_target"
then
rm -rf "$cdrskin_target"
fi
cp -a "$cdrskin_dir" "$cdrskin_target"
# Remove copied vim.swp and binaries
rm "$cdrskin_target"/.*.swp
rm "$cdrskin_target"/*.o
rm "$cdrskin_target"/cdrfifo
rm "$cdrskin_target"/cdrskin
rm "$cdrskin_target"/cleanup
for i in std new make old
do
if test -e "$cdrskin_target"/cdrskin_"$i"
then
rm "$cdrskin_target"/cdrskin_"$i"
fi
done
# Remove eventual SVN stuff from cdrskin directory
for i in .deps .dirstamp .libs
do
if test -e "$cdrskin_target"/"$i"
then
rm -rf "$cdrskin_target"/"$i"
fi
done
# Remove GIFs of cdrskin_eng.html
rm "$cdrskin_target"/doener_*.gif "$cdrskin_target"/doener_*.png
# Remove automatically generated HTML man page
rm "$cdrskin_target"/man_1_cdrskin.html
# Remove all add_ts_changes_to_libburn besides this one
for i in "$cdrskin_target"/add_ts_changes_to_libburn*
do
if test $(basename "$0") = $(basename "$i")
then
dummy=dummy
else
rm $i
fi
done
# Remove libcevap
rm -rf "$target"/libcevap
# Remove unwanted SVN stuff (TODO: avoid downloading it)
for i in "$target"/.svn "$target"/*/.svn
do
if test "$i" = "$target"'/*/.svn'
then
dummy=dummy
else
if test -e "$i"
then
rm -rf "$i"
fi
fi
done
# Make SVN state tarball for the libburn team
tar czf "$cdrskin_tarball_svn" "$target"
# Get over dependecy on autotools. Rely only on cc, make et. al.
# This is not the same as "make dist" but i can do it without
# having to evaluate the quality of said "make dist"
#
( cd "$target" ; ./bootstrap )
# Remove unwanted stuff after bootstrap
for i in "$target"/autom4te.cache
do
if echo "$i" | grep '\*' >/dev/null
then
dummy=dummy
else
if test -e "$i"
then
rm -rf "$i"
fi
fi
done
# Repair non-portable shell code output of ./bootstrap
(
cd "$compile_dir" || exit 1
sed -e 's/^for ac_header in$/test -z 1 \&\& for ac_header in dummy/' \
< ./configure > ./configure-repaired
if test "$?" = 0
then
echo "$0: Empty 'for ac_header in' found in configure." >&2
fi
mv ./configure-repaired ./configure
chmod a+rx,go-w,u+w ./configure
)
# Pack it up to the new libburn+cdrskin-tarball
tar czf "$cdrskin_tarball" "$target"
# Produce a static and a dynamic binary, and a HTML man page
(
cd "$compile_dir" || exit 1
./configure
make
"$compile_cmd" -O2 -do_strip
cp "$compile_result" "../$bintarget_dynamic"
if test -n "$compile_static_opts"
then
"$compile_cmd" $compile_static_opts -O2 -do_strip
cp "$compile_result" "../$bintarget_static"
fi
"$man_to_html_cmd"
mv "$man_page_html" ..
)
# Remove the build area
# Disable this for debugging the merge process
rm -rf "$target"
# Show the result
./"$bintarget_dynamic" -version
./"$bintarget_static" -version
ls -l "$cdrskin_tarball"
ls -l "$bintarget_dynamic"
ls -l "$bintarget_static"
ls -l $(basename "$man_page_html")

View File

@ -20,26 +20,30 @@ set -x
# The script is to be run in the directory above the toplevel
# directory of libburn resp. cdrskin development.
#
# libburn version used: http://libburn.pykix.org
# The top level directory in the SVN snapshot is named
intermediate="./libburn_pykix"
# libburn source used: http://libburnia-project.org
# Downloaded by:
# $ svn co http://libburn-svn.pykix.org/trunk libburn_pykix
# $ svn co http://libburnia-project.org/libburn/tags/... $intermediate
# packed up in a tarball just to save it from inadverted changes by
# $ tar czf libburn_svn.tgz libburn_pykix
# $ tar czf libburn_svn.tgz $intermediate
original="./libburn_svn.tgz"
# Historic moments:
# original="./libburn_svn_A60815.tgz"
# original="./libburn_cdrskin_A60819.tgz"
# The top level directory in that snapshot is named
intermediate="./libburn_pykix"
# My changes are in libburn-0.2.3.ts.develop , mainly in ./cdrskin
# My changes are in $changes , mainly in $changes/cdrskin
changes="./libburn-develop"
changes="./libburn-0.2.3.ts.develop"
skin_rev="0.2.3"
skin_release="0.6.1"
patch_level=""
skin_rev="$skin_release""$patch_level"
# The result directory and the name of the result tarballs
target="./cdrskin-${skin_rev}"
target="./cdrskin-${skin_release}"
cdrskin_tarball="./cdrskin-${skin_rev}.tar.gz"
cdrskin_tarball_svn="./cdrskin-${skin_rev}.svn.tar.gz"
@ -51,7 +55,10 @@ compile_cmd="./cdrskin/compile_cdrskin.sh"
compile_static_opts="-static"
compile_result="cdrskin/cdrskin"
bintarget_dynamic="cdrskin_${skin_rev}-x86-suse9_0"
man_to_html_cmd="./cdrskin/convert_man_to_html.sh"
man_page_html="cdrskin/man_1_cdrskin.html"
bintarget_dynamic="cdrskin_${skin_rev}-amd64-suse10_2"
bintarget_static="$bintarget_dynamic"-static
if test -d "$changes"
@ -107,13 +114,48 @@ then
fi
cp -a "$cdrskin_dir" "$cdrskin_target"
# Remove copied binaries
# Remove copied vim.swp and binaries
rm "$cdrskin_target"/.*.swp
rm "$cdrskin_target"/*.o
rm "$cdrskin_target"/cdrfifo
rm "$cdrskin_target"/cdrskin
rm "$cdrskin_target"/cleanup
rm "$cdrskin_target"/cdrskin_std
rm "$cdrskin_target"/cdrskin_new
rm "$cdrskin_target"/*.o
for i in std new make old
do
if test -e "$cdrskin_target"/cdrskin_"$i"
then
rm "$cdrskin_target"/cdrskin_"$i"
fi
done
# Remove eventual SVN stuff from cdrskin directory
for i in .deps .dirstamp .libs
do
if test -e "$cdrskin_target"/"$i"
then
rm -rf "$cdrskin_target"/"$i"
fi
done
# Remove GIFs of cdrskin_eng.html
rm "$cdrskin_target"/doener_*.gif "$cdrskin_target"/doener_*.png
# Remove automatically generated HTML man page
rm "$cdrskin_target"/man_1_cdrskin.html
# Remove libcevap
rm -rf "$target"/libcevap
# Remove all add_ts_changes_to_libburn besides this one
for i in "$cdrskin_target"/add_ts_changes_to_libburn*
do
if test $(basename "$0") = $(basename "$i")
then
dummy=dummy
else
rm $i
fi
done
# Remove unwanted SVN stuff (TODO: avoid downloading it)
for i in "$target"/.svn "$target"/*/.svn
@ -129,12 +171,6 @@ do
fi
done
## No more : Add own libburn-README in toplevel
# cp -a "$changes"/README "$target"
## No more : Add modified Makefile.am
# cp -a "$changes"/Makefile.am "$target"
# Make SVN state tarball for the libburn team
tar czf "$cdrskin_tarball_svn" "$target"
@ -160,22 +196,39 @@ do
fi
done
# Repair non-portable shell code output of ./bootstrap
(
cd "$compile_dir" || exit 1
sed -e 's/^for ac_header in$/test -z 1 \&\& for ac_header in dummy/' \
< ./configure > ./configure-repaired
if test "$?" = 0
then
echo "$0: Empty 'for ac_header in' found in configure." >&2
fi
mv ./configure-repaired ./configure
chmod a+rx,go-w,u+w ./configure
)
# Pack it up to the new libburn+cdrskin-tarball
tar czf "$cdrskin_tarball" "$target"
# Produce a static and a dynamic binary
# Produce a static and a dynamic binary, and a HTML man page
(
cd "$compile_dir" || exit 1
./configure
make
$compile_cmd -do_strip
"$compile_cmd" -libburn_svn -O2 -do_strip
cp "$compile_result" "../$bintarget_dynamic"
if test -n "$compile_static_opts"
then
$compile_cmd $compile_static_opts -do_strip
"$compile_cmd" $compile_static_opts -libburn_svn -O2 -do_strip
cp "$compile_result" "../$bintarget_static"
fi
# "$compile_cmd" -libburn_svn -O2 -do_diet -do_strip
# cp "$compile_result" "../$bintarget_dynamic"_diet
"$man_to_html_cmd"
mv "$man_page_html" ..
)
# Remove the build area
@ -188,4 +241,5 @@ rm -rf "$target"
ls -l "$cdrskin_tarball"
ls -l "$bintarget_dynamic"
ls -l "$bintarget_static"
ls -l $(basename "$man_page_html")

View File

@ -38,7 +38,9 @@
#define Cdrfifo_ffd_maX 100
/* 1= enable , 0= disable status messages to stderr */
/* 1= enable , 0= disable status messages to stderr
2= report each
*/
static int Cdrfifo_debuG= 0;
@ -48,6 +50,9 @@ struct CdrfifO {
int source_fd;
double in_counter;
double fd_in_counter;
double fd_in_limit;
char *buffer;
int buffer_size;
int buffer_is_full;
@ -72,20 +77,38 @@ struct CdrfifO {
double empty_counter;
double full_counter;
/* eventual ISO-9660 image size obtained from first 64k of input */
double iso_fs_size;
char *iso_fs_descr; /* eventually block 16 to 31 of input */
/* (sequential) fd chaining */
/* fds: 0=source, 1=dest */
int follow_up_fds[Cdrfifo_ffd_maX][2];
/* index of first byte in buffer which does not belong to predecessor fd */
int follow_up_eop[Cdrfifo_ffd_maX];
/* if follow_up_eop[i]==buffer_size : read_idx was 0 when this was set */
int follow_up_was_full_buffer[Cdrfifo_ffd_maX];
/* index of first byte in buffer which belongs to [this] fd pair */
int follow_up_sod[Cdrfifo_ffd_maX];
/* values for fd_in_limit */
double follow_up_in_limits[Cdrfifo_ffd_maX];
/* number of defined follow-ups */
int follow_up_fd_counter;
/* index of currently active (i.e. reading) follow-up */
int follow_up_fd_idx;
/* (simultaneous) peer chaining */
struct CdrfifO *next;
struct CdrfifO *prev;
/* rank in peer chain */
int chain_idx;
};
@ -117,6 +140,8 @@ int Cdrfifo_new(struct CdrfifO **ff, int source_fd, int dest_fd,
buffer_size+= chunk_size-(buffer_size%chunk_size);
o->source_fd= source_fd;
o->in_counter= 0.0;
o->fd_in_counter= 0;
o->fd_in_limit= -1.0;
o->buffer= NULL;
o->buffer_is_full= 0;
o->buffer_size= buffer_size;
@ -137,13 +162,18 @@ int Cdrfifo_new(struct CdrfifO **ff, int source_fd, int dest_fd,
o->get_counter= 0.0;
o->empty_counter= 0.0;
o->full_counter= 0.0;
o->iso_fs_size= -1.0;
o->iso_fs_descr= NULL;
for(i= 0; i<Cdrfifo_ffd_maX; i++) {
o->follow_up_fds[i][0]= o->follow_up_fds[i][1]= -1;
o->follow_up_eop[i]= o->follow_up_sod[i]= -1;
o->follow_up_was_full_buffer[i]= 0;
o->follow_up_in_limits[i]= -1.0;
}
o->follow_up_fd_counter= 0;
o->follow_up_fd_idx= -1;
o->next= o->prev= NULL;
o->chain_idx= 0;
o->buffer= TSOB_FELD(char,buffer_size);
if(o->buffer==NULL)
goto failed;
@ -194,6 +224,8 @@ int Cdrfifo_destroy(struct CdrfifO **ff, int flag)
/* eventual closing of source fds is the job of the calling application */
if(o->iso_fs_descr!=NULL)
free((char *) o->iso_fs_descr);
if(o->buffer!=NULL)
free((char *) o->buffer);
free((char *) o);
@ -224,6 +256,26 @@ int Cdrfifo_set_speed_limit(struct CdrfifO *o, double bytes_per_second,
}
/** Set a fixed size for input in order to cut off any unwanted tail
@param o The fifo object
@param idx index for fds attached via Cdrfifo_attach_follow_up_fds(),
first attached is 0, <0 directs limit to active fd limit
(i.e. first track is -1, second track is 0, third is 1, ...)
*/
int Cdrfifo_set_fd_in_limit(struct CdrfifO *o, double fd_in_limit, int idx,
int flag)
{
if(idx<0) {
o->fd_in_limit= fd_in_limit;
return(1);
}
if(idx >= o->follow_up_fd_counter)
return(0);
o->follow_up_in_limits[idx]= fd_in_limit;
return(1);
}
int Cdrfifo_set_fds(struct CdrfifO *o, int source_fd, int dest_fd, int flag)
{
o->source_fd= source_fd;
@ -244,6 +296,7 @@ int Cdrfifo_get_fds(struct CdrfifO *o, int *source_fd, int *dest_fd, int flag)
fifo buffer when its predecessors are exhausted. Reading will start as
soon as reading of the predecessor encounters EOF. Writing will start
as soon as all pending predecessor data are written.
@return index number of new item + 1, <=0 indicates error
*/
int Cdrfifo_attach_follow_up_fds(struct CdrfifO *o, int source_fd, int dest_fd,
int flag)
@ -253,7 +306,7 @@ int Cdrfifo_attach_follow_up_fds(struct CdrfifO *o, int source_fd, int dest_fd,
o->follow_up_fds[o->follow_up_fd_counter][0]= source_fd;
o->follow_up_fds[o->follow_up_fd_counter][1]= dest_fd;
o->follow_up_fd_counter++;
return(1);
return(o->follow_up_fd_counter);
}
@ -262,10 +315,16 @@ int Cdrfifo_attach_follow_up_fds(struct CdrfifO *o, int source_fd, int dest_fd,
*/
int Cdrfifo_attach_peer(struct CdrfifO *o, struct CdrfifO *next, int flag)
{
int idx;
struct CdrfifO *s;
for(s= o;s->prev!=NULL;s= s->prev); /* determine start of o-chain */
for(;o->next!=NULL;o= o->next); /* determine end of o-chain */
for(;next->prev!=NULL;next= next->prev); /* determine start of next-chain */
next->prev= o;
o->next= next;
for(idx= 0;s!=NULL;s= s->next)
s->chain_idx= idx++;
return(1);
}
@ -338,6 +397,21 @@ int Cdrfifo_get_min_fill(struct CdrfifO *o, int *total_min_fill,
}
int Cdrfifo_get_iso_fs_size(struct CdrfifO *o, double *size_in_bytes, int flag)
{
*size_in_bytes= o->iso_fs_size;
return(o->iso_fs_size>=2048);
}
int Cdrfifo_adopt_iso_fs_descr(struct CdrfifO *o, char **pt, int flag)
{
*pt= o->iso_fs_descr;
o->iso_fs_descr= NULL;
return(*pt!=NULL);
}
/** Get counters which are mentioned by cdrecord at the end of burning.
It still has to be examined wether they mean what i believe they do.
*/
@ -346,7 +420,7 @@ int Cdrfifo_get_cdr_counters(struct CdrfifO *o,
double *empty_counter, double *full_counter,
int flag)
{
*put_counter= o->put_counter;;
*put_counter= o->put_counter;
*get_counter= o->get_counter;
*empty_counter= o->empty_counter;
*full_counter= o->full_counter;
@ -371,10 +445,26 @@ int Cdrfifo_eop_adjust(struct CdrfifO *o,int *buffer_fill, int *eop_idx,
for(i=0; i<=o->follow_up_fd_idx; i++) {
if(o->follow_up_eop[i]>=0 && o->follow_up_eop[i]>=o->read_idx) {
eop_is_near= 1;
valid_fill= o->follow_up_eop[i]-o->read_idx;
if(o->follow_up_eop[i]<o->buffer_size || o->read_idx>0) {
valid_fill= o->follow_up_eop[i]-o->read_idx;
o->follow_up_was_full_buffer[i]= 0;
} else {
/*
If an input fd change hit exactly the buffer end then follow_up_eop
points to buffer_size and not to 0. So it is time to switch output
pipes unless this is immediately after follow_up_eop was set and
read_idx was 0 (... if this is possible at all while write_idx is 0).
follow_up_was_full_buffer was set in this case and gets invalid as
soon as a non-0 read_idx is detected (see above).
*/
if(o->follow_up_was_full_buffer[i])
valid_fill= o->buffer_size;
else
valid_fill= 0; /* the current pipe is completely served */
}
if(valid_fill==0)
*eop_idx= i;
else if(valid_fill<=o->chunk_size)
else if(valid_fill<o->chunk_size)
eop_is_near= 2; /* for debugging. to carry a break point */
break;
}
@ -399,7 +489,7 @@ static int Cdrfifo_setup_try(struct CdrfifO *o, struct timeval start_tv,
*/
{
int buffer_space,buffer_fill,eop_reached= -1,eop_is_near= 0,was_closed;
int fd_buffer_fill;
int fd_buffer_fill, eop_reached_counter= 0;
struct timeval current_tv;
struct timezone tz;
double diff_time,diff_counter,limit,min_wait_time;
@ -428,21 +518,26 @@ setup_try:;
if(eop_reached>=0) { /* switch to next output fd */
o->dest_fd= o->follow_up_fds[eop_reached][1];
if(Cdrfifo_debuG)
fprintf(stderr,"\ncdrfifo %d: new fifo destination fd : %d\n",
o->chain_idx,o->dest_fd);
o->read_idx= o->follow_up_sod[eop_reached];
o->follow_up_eop[eop_reached]= -1;
eop_is_near= 0;
eop_reached= -1;
eop_reached_counter= 0;
goto setup_try;
} else {
/* work is really done */
if((!was_closed) && ((flag&1)||Cdrfifo_debuG))
fprintf(stderr,
"\ncdrfifo_debug: w=%d r=%d | b=%d s=%d | i=%.f o=%.f (done)\n",
o->write_idx,o->read_idx,buffer_fill,buffer_space,
"\ncdrfifo %d: w=%d r=%d | b=%d s=%d | i=%.f o=%.f (done)\n",
o->chain_idx,o->write_idx,o->read_idx,buffer_fill,buffer_space,
o->in_counter,o->out_counter);
return(2);
}
}
} else if(eop_reached>=0)
eop_reached_counter++;
if(o->interval_counter>0) {
if(o->total_min_fill>buffer_fill && o->source_fd>=0)
o->total_min_fill= buffer_fill;
@ -544,7 +639,8 @@ return: <0 = error , 0 = idle , 1 = did some work
if(ret==-1) {
/* >>> handle broken pipe */;
fprintf(stderr,"\ncdrfifo: on write: errno=%d , \"%s\"\n",errno,
fprintf(stderr,"\ncdrfifo %d: on write: errno=%d , \"%s\"\n",
o->chain_idx,errno,
errno==0?"-no error code available-":strerror(errno));
if(!(flag&4))
@ -567,26 +663,40 @@ after_write:;
can_read= o->chunk_size;
if(o->write_idx<o->read_idx && o->write_idx+can_read > o->read_idx)
can_read= o->read_idx - o->write_idx;
ret= read(o->source_fd,o->buffer+o->write_idx,can_read);
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;
ret= 0;
if(can_read>0)
ret= read(o->source_fd,o->buffer+o->write_idx,can_read);
if(ret==-1) {
/* >>> handle input error */;
fprintf(stderr,"\ncdrfifo: on read: errno=%d , \"%s\"\n",errno,
fprintf(stderr,"\ncdrfifo %d: on read: errno=%d , \"%s\"\n",
o->chain_idx,errno,
errno==0?"-no error code available-":strerror(errno));
o->source_fd= -1;
} else if(ret==0) { /* eof */
/* activate eventual follow-up source fd */
if(Cdrfifo_debuG || (flag&1))
fprintf(stderr,"\ncdrfifo: on read(%d,buffer,%d): eof\n",
o->source_fd,can_read);
fprintf(stderr,"\ncdrfifo %d: on read(%d,buffer,%d): eof\n",
o->chain_idx,o->source_fd,can_read);
if(o->follow_up_fd_idx+1 < o->follow_up_fd_counter) {
idx= ++(o->follow_up_fd_idx);
o->source_fd= o->follow_up_fds[idx][0];
/* End-Of-Previous */
if(o->write_idx==0)
if(o->write_idx==0) {
o->follow_up_eop[idx]= o->buffer_size;
else
/* A70304 : can this happen ? */
o->follow_up_was_full_buffer[idx]= (o->read_idx==0);
if(Cdrfifo_debuG || (flag&1))
fprintf(stderr,"\ncdrfifo %d: write_idx 0 on eop: read_idx= %d\n",
o->chain_idx,o->read_idx);
} else
o->follow_up_eop[idx]= o->write_idx;
/* Start-Of-Data . Try to start at next full chunk */
sod= o->write_idx;
@ -599,8 +709,11 @@ after_write:;
sod= 0;
o->follow_up_sod[idx]= sod;
o->write_idx= sod;
o->fd_in_counter= 0;
o->fd_in_limit= o->follow_up_in_limits[idx];
if(Cdrfifo_debuG || (flag&1))
fprintf(stderr,"\ncdrfio: new fifo source fd : %d\n",o->source_fd);
fprintf(stderr,"\ncdrfifo %d: new fifo source fd : %d\n",
o->chain_idx,o->source_fd);
} else {
o->source_fd= -1;
}
@ -608,6 +721,7 @@ after_write:;
did_work= 1;
o->put_counter++;
o->in_counter+= ret;
o->fd_in_counter+= ret;
o->write_idx+= ret;
if(o->write_idx>=o->buffer_size)
o->write_idx= 0;
@ -732,13 +846,13 @@ ex:;
} else
elapsed= wait_usec;
if(elapsed>=wait_usec) {
if((flag&1)||Cdrfifo_debuG) {
if((flag&1)||Cdrfifo_debuG>=2) {
fprintf(stderr,"\n");
for(ff= o; ff!=NULL; ff= ff->next) {
buffer_space= Cdrfifo_tell_buffer_space(ff,0);
fprintf(stderr,
"cdrfifo_debug: w=%d r=%d | b=%d s=%d | i=%.f o=%.f\n",
ff->write_idx,ff->read_idx,
"cdrfifo %d: w=%d r=%d | b=%d s=%d | i=%.f o=%.f\n",
ff->chain_idx,ff->write_idx,ff->read_idx,
ff->buffer_size-buffer_space,buffer_space,
ff->in_counter,ff->out_counter);
}
@ -751,7 +865,7 @@ ex:;
/** Fill the fifo as far as possible without writing to destination fd */
int Cdrfifo_fill(struct CdrfifO *o, int flag)
int Cdrfifo_fill(struct CdrfifO *o, int size, int flag)
{
int ret,fill= 0,space,state;
@ -765,6 +879,8 @@ int Cdrfifo_fill(struct CdrfifO *o, int flag)
} else if(state!=1)
break;
if(space<=0)
break;
if(size>=0 && fill>=size)
break;
ret= Cdrfifo_try_to_work(o,100000,NULL,NULL,2);
if(ret<0) {
@ -776,6 +892,29 @@ int Cdrfifo_fill(struct CdrfifO *o, int flag)
if(ret==2)
break;
}
#ifndef Cdrfifo_standalonE
if(fill>=32*2048) {
int Scan_for_iso_size(unsigned char data[2048], double *size_in_bytes,
int flag);
int bs= 16*2048;
double size;
/* memorize blocks 16 to 31 */
if(o->iso_fs_descr!=NULL)
free((char *) o->iso_fs_descr);
o->iso_fs_descr= TSOB_FELD(char,bs);
if(o->iso_fs_descr==NULL)
return(-1);
memcpy(o->iso_fs_descr,o->buffer+bs,bs);
/* try to obtain ISO-9660 file system size from block 16 */
ret= Scan_for_iso_size((unsigned char *) (o->buffer+bs), &size, 0);
if(ret>0)
o->iso_fs_size= size;
}
#endif
o->total_min_fill= fill;
o->interval_min_fill= fill;
return(1);
@ -828,6 +967,76 @@ double Scanf_io_size(char *text, int flag)
}
/* This is a hardcoded test mock-up for two simultaneous fifos of which the
one runs with block size 2048 and feeds the other which runs with 2352.
Both fifos have the same number of follow_up pipes (tracks) which shall
be connected 1-to-1.
*/
int Test_mixed_bs(char **paths, int path_count,
int fs_size, double speed_limit, double interval, int flag)
/*
bit0= debugging verbousity
*/
{
int fd_in[100],fd_out[100],ret,pipe_fds[100][2],real_out[100];
int i,iv,stall_counter= 0,cycle_counter= 0.0;
char buf[10240], target_path[80];
double in_counter, out_counter, prev_in= -1.0, prev_out= -1.0;
struct CdrfifO *ff_in= NULL, *ff_out= NULL;
if(path_count<1)
return(2);
Cdrfifo_new(&ff_in,fd_in[0],fd_out[0],2048,fs_size,0);
for(i= 0; i<path_count; i++) {
fd_in[2*i]= open(paths[i],O_RDONLY);
if(fd_in[2*i]==-1)
return(0);
if(pipe(pipe_fds[2*i])==-1)
return(-1);
fd_out[2*i]= pipe_fds[2*i][1];
if(i==0)
ret= Cdrfifo_new(&ff_in,fd_in[2*i],fd_out[2*i],2048,fs_size,0);
else
ret= Cdrfifo_attach_follow_up_fds(ff_in,fd_in[2*i],fd_out[2*i],0);
if(ret<=0)
return(ret);
fd_in[2*i+1]= pipe_fds[2*i][0];
sprintf(target_path,"/dvdbuffer/fifo_mixed_bs_test_%d",i);
fd_out[2*i+1]= open(target_path,O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
if(i==0)
ret= Cdrfifo_new(&ff_out,fd_in[2*i+1],fd_out[2*i+1],2352,fs_size,0);
else
ret= Cdrfifo_attach_follow_up_fds(ff_out,fd_in[2*i+1],fd_out[2*i+1],0);
if(ret<=0)
return(ret);
fprintf(stderr,"test_mixed_bs: %d : %2d fifo %2d pipe %2d fifo %2d : %s\n",
i, fd_in[2*i],fd_out[2*i],fd_in[2*i+1],fd_out[2*i+1], target_path);
}
Cdrfifo_attach_peer(ff_in,ff_out,0);
/* Let the fifos work */
iv= interval*1e6;
while(1) {
ret= Cdrfifo_try_to_work(ff_in,iv,NULL,NULL,flag&1);
if(ret<0 || ret==2) { /* <0 = error , 2 = work is done */
fprintf(stderr,"\ncdrfifo %d: fifo ended work with ret=%d\n",
ff_in->chain_idx,ret);
if(ret<0)
return(-7);
break;
}
cycle_counter++;
Cdrfifo_get_counters(ff_in, &in_counter, &out_counter, 0);
if(prev_in == in_counter && prev_out == out_counter)
stall_counter++;
prev_in= in_counter;
prev_out= out_counter;
}
return(1);
}
/* This is a hardcoded test mock-up for two simultaneous fifos of which the
first one simulates the cdrskin fifo feeding libburn and the second one
simulates libburn and the burner at given speed. Both have two fd pairs
@ -886,7 +1095,8 @@ int Test_multi(int fs_size, double speed_limit, double interval, int flag)
while(1) {
ret= Cdrfifo_try_to_work(ff1,iv,NULL,NULL,flag&1);
if(ret<0 || ret==2) { /* <0 = error , 2 = work is done */
fprintf(stderr,"\ncdrfifo: fifo ended work with ret=%d\n",ret);
fprintf(stderr,"\ncdrfifo %d: fifo ended work with ret=%d\n",
ff1->chain_idx,ret);
if(ret<0)
return(-7);
break;
@ -945,6 +1155,13 @@ int main(int argc, char **argv)
} else if(strncmp(argv[i],"vb=",3)==0) {
sscanf(argv[i]+3,"%d",&verbous);
} else if(strcmp(argv[i],"-mixed_bs_test")==0) {
ret= Test_mixed_bs(argv+i+1,argc-i-1,
(int) fs_value,speed_limit,interval,(verbous>=2));
fprintf(stderr,"Test_mixed_bs(): ret= %d\n",ret);
exit(ret<0);
} else if(strcmp(argv[i],"-multi_test")==0) {
if(speed_limit==0.0)
@ -988,7 +1205,7 @@ int main(int argc, char **argv)
if(speed_limit!=0.0)
Cdrfifo_set_speed_limit(ff,speed_limit,0);
if(fill_buffer) {
ret= Cdrfifo_fill(ff,0);
ret= Cdrfifo_fill(ff,0,0);
if(ret<=0) {
fprintf(stderr,
"cdrfifo: FATAL : initial filling of fifo buffer failed\n");

View File

@ -15,7 +15,7 @@
/** The fifo buffer which will smoothen the data stream from data provider
to data consumer. Although this is not a mandatory lifesavier for modern
to data consumer. Although this is not a mandatory lifesaver for modern
burners any more, a fifo can speed up burning of data which is delivered
with varying bandwidths (e.g. compressed archives created on the fly
or mkisofs running at its speed limit.).
@ -64,6 +64,16 @@ int Cdrfifo_get_sizes(struct CdrfifO *o, int *chunk_size, int *buffer_size,
int Cdrfifo_set_speed_limit(struct CdrfifO *o, double bytes_per_second,
int flag);
/** Set a fixed size for input in order to cut off any unwanted tail
@param o The fifo object
@param idx index for fds attached via Cdrfifo_attach_follow_up_fds(),
first attached is 0, <0 directs limit to active fd limit
(i.e. first track is -1, second track is 0, third is 1, ...)
*/
int Cdrfifo_set_fd_in_limit(struct CdrfifO *o, double fd_in_limit, int idx,
int flag);
int Cdrfifo_set_fds(struct CdrfifO *o, int source_fd, int dest_fd, int flag);
int Cdrfifo_get_fds(struct CdrfifO *o, int *source_fd, int *dest_fd, int flag);
@ -72,6 +82,7 @@ int Cdrfifo_get_fds(struct CdrfifO *o, int *source_fd, int *dest_fd, int flag);
fifo buffer when its predecessors are exhausted. Reading will start as
soon as reading of the predecessor encounters EOF. Writing will start
as soon as all pending predecessor data are written.
@return index number of new item + 1, <=0 indicates error
*/
int Cdrfifo_attach_follow_up_fds(struct CdrfifO *o, int source_fd, int dest_fd,
int flag);
@ -106,6 +117,21 @@ int Cdrfifo_get_cdr_counters(struct CdrfifO *o,
double *empty_counter, double *full_counter,
int flag);
/** Inquire the eventually detected size of an eventual ISO-9660 file system
@return 0=no ISO resp. size detected, 1=size_in_bytes is valid
*/
int Cdrfifo_get_iso_fs_size(struct CdrfifO *o, double *size_in_bytes,int flag);
/** Take over the eventually memorized blocks 16 to 31 of input (2 kB each).
The fifo forgets the blocks by this call. I.e. a second one will return 0.
After this call it is the responsibility of the caller to dispose the
retrieved memory via call free().
@param pt Will be filled either with NULL or a pointer to 32 kB of data
@return 0=nothing is buffered, 1=pt points to valid freeable data
*/
int Cdrfifo_adopt_iso_fs_descr(struct CdrfifO *o, char **pt, int flag);
/** Check for pending data at the fifo's source file descriptor and wether the
fifo is ready to take them. Simultaneously check the buffer for existing
@ -134,10 +160,11 @@ int Cdrfifo_get_cdr_counters(struct CdrfifO *o,
int Cdrfifo_try_to_work(struct CdrfifO *o, int wait_usec,
char *reply_buffer, int *reply_count, int flag);
/** Fill the fifo as far as possible without writing to destination fd
/** Fill the fifo as far as possible without writing to destination fd.
@param size if >=0 : end filling after the given number of bytes
@return 1 on success, <=0 on failure
*/
int Cdrfifo_fill(struct CdrfifO *o, int flag);
int Cdrfifo_fill(struct CdrfifO *o, int size, int flag);
#endif /* Cdrfifo_headerfile_includeD */

1343
cdrskin/cdrskin.1 Normal file

File diff suppressed because it is too large Load Diff

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, burn, CD, linux, CDR, CD-R, CDRW, CD-RW, cdrecord, compatible, scdbackup, burning">
<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>
@ -11,36 +11,44 @@
<FONT SIZE=+1>
<CENTER>
<P><H2>Homepage of</H2><H1><BR>cdrskin</H1><BR>
<!-- <FONT SIZE=+0><A HREF="cdrskin_ger.html">deutsch (german)</A></FONT> -->
<A HREF="http://en.wikipedia.org/wiki/D%C3%B6ner_kebab">
<IMG SRC="doener_150x200_tr_octx.png" BORDER=0
ALT="cdrskin logo: Doener mit Scharf">
</A>
<P><H2> Homepage of </H2>
<H1> cdrskin </H1>
<H2>Limited cdrecord compatibility wrapper for libburn</H2>
</CENTER>
<P>
<H2>Purpose:</H2>
<UL>
<LI>Burns preformatted data to CD-R or CD-RW</LI>
</UL>
Burns preformatted data to CD, DVD, and BD media:<BR>
CD-R, DVD-R, DVD+R, DVD+R/DL, BD-R, CD-RW, DVD-RW, DVD-RAM, DVD+RW, BD-RE
</P>
<P>
<HR>
<A HREF="#download">Direct hop to download links -></A>
<P>
<H2>Hardware requirements:</H2>
A CD recorder suitable for
<A HREF="http://libburn.pykix.org">libburn.pykix.org</A>
(SCSI or IDE/ATAPI writers compliant to mmc standard).
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).
<BR>
</P>
<P>
<H2>Software requirements :</H2>
<DL>
<DT>Linux kernel 2.4 or higher</DT>
<DD>With kernel 2.4 the drive has to be under ide-scsi emulation.</DD>
<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>ATAPI/CAM support has to be enabled in the kernel, see atapicam(4).</DD>
<DT>libpthread</DT>
<DD>is supposed to be a standard system component.</DD>
</DL>
@ -51,14 +59,18 @@ A CD recorder suitable for
GPL software included:<BR>
</H2>
<DL>
<DT>libburn-0.2.2</DT>
<DD>(by Derek Foreman, Ben Jansens, and team of libburn.pykix.org)</DD>
<DD>transfers data to CD</DD>
<DT>libburn-0.6.0</DT>
<DD>(founded by Derek Foreman and Ben Jansens,
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 Linux and FreeBSD systems
only.<BR>
Ports to other usable systems are appreciated. Reports are welcome.
</P>
@ -76,106 +88,149 @@ Ports to other usable systems are appreciated. Reports are welcome.
<P>
<H2>Commands:</H2>
<DL>
<DT>The goal is to provide some of cdrecord's options in a compatible way.
This has been achieved quite sufficiently for the needs of backup tool
<A HREF="http://scdbackup.sourceforge.net/main_eng.html">scdbackup</A>
and for data CD projects of <A HREF="http://www.k3b.org">K3b</A>
(see <A HREF="#examples">examples</A>).<BR>
Further enhancements depend on people who can describe and discuss their
wishes as well as on the development of libburn.</DT>
<DT>The most common options of cdrecord for data and audio on CD media
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
BD-R. Write mode -tao works with anything but quickly blanked DVD-RW.
</DT>
<BR><BR>
<DT><A HREF="cdrskin_help">cdrskin -help</A></DT>
<DD>reports the cdrecord compatible options</DD>
<DT><A HREF="cdrskin__help">cdrskin --help</A></DT>
<DD>reports the non-cdrecord options</DD>
<DT><A HREF="http://cdrecord.berlios.de/old/private/man/cdrecord-2.0.html">man cdrecord</A></DT>
<DD>documents the standard for which cdrskin is striving.
<B>Do not bother Joerg Schilling with any cdrskin problems.</B>
<DT>Get an overview of drives and their addresses</DT>
<DD>#<KBD>&nbsp;cdrskin -scanbus</KBD></DD>
<DD>#<KBD>&nbsp;cdrskin dev=ATA -scanbus</KBD></DD>
<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>&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>
<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>
<DT>Format DVD-RW to avoid need for blanking before re-use:</DT>
<DD>$<KBD>&nbsp;cdrskin -v dev=/dev/sr0 blank=format_overwrite</KBD></DD>
<DT>De-format DVD-RW to make it capable of multi-session again:</DT>
<DD>$<KBD>&nbsp;cdrskin -v dev=/dev/sr0 blank=deformat_sequential</KBD></DD>
<DT>Write ISO-9660 filesystem image as only one to blank or formatted media:
</DT>
<DD>$<KBD>&nbsp;cdrskin -v dev=/dev/hdc speed=12 fs=8m \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;blank=as_needed -eject padsize=300k my_image.iso</KBD></DD>
<DT>Write compressed afio archive on-the-fly:</DT>
<DD>$<KBD>&nbsp;find . | afio -oZ - | \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;cdrskin -v dev=0,1,0 fs=32m speed=8 \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;blank=as_needed padsize=300k -</KBD></DD>
<DT>Write several sessions to the same CD, DVD-R[W] or DVD+R[/DL]:</DT>
<DD>$<KBD>&nbsp;cdrskin dev=/dev/hdc -v padsize=300k -multi 1.iso</KBD>
</DD>
<DD>$<KBD>&nbsp;cdrskin dev=/dev/hdc -v padsize=300k -multi 2.iso</KBD>
</DD>
<DD>$<KBD>&nbsp;cdrskin dev=/dev/hdc -v padsize=300k -multi 3.iso</KBD>
</DD>
<DD>$<KBD>&nbsp;cdrskin dev=/dev/hdc -v padsize=300k 4.iso</KBD></DD>
<DT>Get multi-session info for option -C of program mkisofs:</DT>
<DD>$<KBD>&nbsp;c_values=$(cdrskin dev=/dev/sr0 -msinfo 2>/dev/null)</KBD></DD>
<DD>$<KBD>&nbsp;mkisofs ... -C "$c_values" ...</KBD></DD>
<DT>Inquire free space on media for a -multi run:</DT>
<DD>$<KBD>&nbsp;x=$(cdrskin dev=/dev/sr0 -multi \</KBD></DD>
<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>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>
<DT>Get overview of the cdrecord compatible options:</DT>
<DD>$<KBD>&nbsp;<A HREF="cdrskin_help">cdrskin -help</A></KBD></DD>
<DT>Get overview of the non-cdrecord options:</DT>
<DD>$<KBD>&nbsp;<A HREF="cdrskin__help">cdrskin --help</A></KBD></DD>
<DT>Read the detailed manual page:</DT>
<DD>$<KBD>&nbsp;<A HREF="man_1_cdrskin.html">man cdrskin</A></KBD></DD>
</DL>
<DL>
<DT>Read about the standard for which cdrskin is striving:</DT>
<DD>$<KBD>&nbsp;
<A HREF="http://cdrecord.berlios.de/old/private/man/cdrecord-2.0.html">
man cdrecord</A></KBD></DD>
<DD><B>Do not bother Joerg Schilling with any cdrskin problems.</B>
(Be cursed if you install cdrskin as "cdrecord" without clearly forwarding
this "don't bother Joerg" demand.)
</DD>
<DT>Currently (and sparsely) supported gestures :</DT>
<DD>$ cdrskin -scanbus</DD>
<DD>$ cdrskin dev=1,1,0 -checkdrive</DD>
<DD>$ cdrskin dev=1,1,0 -atip</DD>
<DD>$ cdrskin -v dev=1,1,0 blank=all -eject</DD>
<DD>$ cdrskin -v dev=1,1,0 blank=fast -eject</DD>
<DD>$ cdrskin -v dev=1,1,0 speed=12 fs=8m -sao driveropts=burnfree -eject padsize=300k my_image.iso</DD>
<DD>$ cdrskin -v dev=1,1,0 ... ... track_1.iso padsize=300k track_2.afio</DD>
<DD>$ find . | afio -oZ - | cdrskin -v dev=1,1,0 fs=32m speed=8 -sao driveropts=burnfree padsize=300k tsize=650m -</DD>
</DL>
</P>
<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
<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>
<H2>Known deficiencies:</H2>
<UL>
<DT></DT>
<LI>
Option -audio is enabled but by default not advertised via option -help,
because no beheading of .au or .wav files takes place yet.
<BR>Note: In development version 0.2.3 there is automatic extraction of
.wav and .au. So -audio is fully supported.
</LI>
<LI>
Burns only a single closed session. No -multi option yet.
</LI>
<LI>
No TAO mode and therefore no writing on-the-fly without a predefined
source size.
</LI>
<LI>
cdrskin -scanbus or --devices hangs for quite a while if there is
a CD drive which does not work properly (e.g. because it has individual
problems with DMA).
So if the superuser gets no result with cdrskin --devices then one should
disable DMA with the problematic CD drives
(like: <KBD>hdparm -d0 /dev/hdd</KBD> )
and try again.<BR>
In severe cases it might be necessary to guess the device name /dev/sgN resp.
/dev/hdX of the non-ill burner if it cannot be found otherwise among its
ill peers. Alternatively one can guess the address of the ill device, remove
rw-permissions and retry the bus scan as non-superuser.
</UL>
</P>
<HR>
<A NAME="download"></A>
<P>
<DL>
<DT>Download as source code (see README):</DT>
<DD><A HREF="cdrskin-0.2.2.tar.gz">cdrskin-0.2.2.tar.gz</A>
(450 KB).
<DD><A HREF="cdrskin-0.6.0.pl01.tar.gz">cdrskin-0.6.0.pl01.tar.gz</A>
(745 KB).
</DD>
<DD>
The "stable" cdrskin tarballs are source code identical with "stable"
libburn releases or with "stabilized" libburn SVN snapshots. They get
produced via a different procedure, though.<BR>
The cdrskin tarballs are source code identical with libburn releases
of the same version number.
They get produced via a different procedure, though.<BR>
cdrskin is part of libburn - full libburn is provided with cdrskin releases.
</DD>
<!-- This is not offered any more since spring 2008
<DD>&nbsp;</DD>
<DT>Download as single x86 binaries (untar and move to /usr/bin/cdrskin):</DT>
<DD><A HREF="cdrskin_0.2.2-x86-suse9_0.tar.gz">
cdrskin_0.2.2-x86-suse9_0.tar.gz</A>, (60 KB),
<DD><A HREF="cdrskin_0.4.2.pl00-x86-suse9_0.tar.gz">
cdrskin_0.4.2.pl00-x86-suse9_0.tar.gz</A>, (110 KB),
<DL>
<DD>runs on SuSE 9.0 (2.4.21) , RIP-14.4 (2.6.14) ,
Gentoo (2.6.15 x86_64 Athlon).</DD>
</DL>
<DD><A HREF="cdrskin_0.2.2-x86-suse9_0-static.tar.gz">
cdrskin_0.2.2-x86-suse9_0-static.tar.gz</A>, (250 KB), -static compiled,
<DD><A HREF="cdrskin_0.4.2.pl00-x86-suse9_0-static.tar.gz">
cdrskin_0.4.2.pl00-x86-suse9_0-static.tar.gz</A>, (310 KB), -static compiled,
<DL>
<DD>runs on SuSE 7.2 (2.4.4), and on the systems above.</DD>
</DL>
</DD>
<DD>&nbsp;</DD>
-->
</DL>
<DL><DT>Documentation:</DT>
<DD><A HREF="README_cdrskin">README</A> a short introduction</DD>
<DD><A HREF="README_cdrskin">README</A> an introduction</DD>
<DD><A HREF="cdrskin__help">cdrskin --help</A> non-cdrecord options</DD>
<DD><A HREF="cdrskin_help">cdrskin -help</A> cdrecord compatible options</DD>
<DD><A HREF="man_1_cdrskin.html">man cdrskin</A> the manual page</DD>
<DD>&nbsp;</DD>
</DL>
<DL><DT>Contact:</DT>
<DD>Thomas Schmitt, <A HREF="mailto:scdbackup@gmx.net">scdbackup@gmx.net</A></DD>
<DD>libburn development mailing list,
<A HREF="mailto:libburn-hackers@pykix.org">libburn-hackers@pykix.org</A></DD>
</DL>
<DL><DT>License:</DT>
<DD><A HREF="COPYING_cdrskin">GPL</A>, an <A HREF="http://www.opensource.org/">Open Source</A> approved license</DD>
@ -185,36 +240,56 @@ cdrskin_0.2.2-x86-suse9_0-static.tar.gz</A>, (250 KB), -static compiled,
<HR>
<P>
Enhancements towards previous stable version cdrskin-0.5.8.pl00:
<UL>
<LI>Formatting and writing of BD-R media</LI>
<!--
<LI>none</LI>
-->
</UL>
Bug fixes towards cdrskin-0.5.8.pl00:
<UL>
<LI>none</LI>
<!--
-->
</UL>
Bug fixes towards cdrskin-0.6.0.pl00:
<UL>
<LI>BD-R media were not closed properly.
The last session staid open and unreadable.</LI>
<!--
-->
</UL>
</P>
<HR>
<P>
<DL>
<DT>Development snapshot, version 0.2.3 :</DT>
<DT><H3>Development snapshot, version 0.6.1 :</H3></DT>
<DD>Enhancements towards current stable version 0.6.0.pl00:
<UL>
<LI>none yet</LI>
<!--
-->
</UL>
</DD>
<DD>&nbsp;</DD>
<DD>Contains non-critical bug fix about failure to eject.</DD>
<DD>&nbsp;</DD>
<DD>Enhancements towards stable version:
<UL>
<LI>cdrecord compatibility with addresses of form [ATA:]Bus,Target,Lun.</LI>
<LI>Drives adressable via links and device siblings (/dev/cdrom , /dev/scd0).
</LI>
<LI>Automatic -audio extraction with .wav files and .au files.
<BR>&nbsp;$ cdrskin -v dev=1,1,0 track1.wav track2.au -audio -swab track3.raw
</LI>
<LI>Comments and empty lines allowed in startup files.</LI>
<LI>Options -scanbus and --devices print SORRY messages about busy drives.
</LI>
<LI>Drive buffer fill indicator reports realistic percentage numbers.</LI>
<LI>Option -toc is supported, drive firmware revision gets displayed.</LI>
</UL></DD>
<DD>&nbsp;</DD>
<DD><A HREF="README_cdrskin_devel">README 0.2.3</A>
<DD><A HREF="cdrskin__help_devel">cdrskin_0.2.3 --help</A></DD>
<DD><A HREF="cdrskin_help_devel">cdrskin_0.2.3 -help</A></DD>
<DD><A HREF="README_cdrskin_devel">README 0.6.1</A>
<DD><A HREF="cdrskin__help_devel">cdrskin_0.6.1 --help</A></DD>
<DD><A HREF="cdrskin_help_devel">cdrskin_0.6.1 -help</A></DD>
<DD><A HREF="man_1_cdrskin_devel.html">man cdrskin (as of 0.6.1)</A></DD>
<DD>&nbsp;</DD>
<DT>Maintainers of cdrskin unstable packages please use SVN of
<A HREF="http://libburn.pykix.org"> libburn.pykix.org</A></DT>
<DD>Download: <KBD><B>svn co http://libburn-svn.pykix.org/trunk libburn_pykix</B>
<A HREF="http://libburnia-project.org"> libburnia-project.org</A></DT>
<DD>Download: <KBD><B>svn co http://svn.libburnia-project.org/libburn/trunk libburn</B>
</KBD></DD>
<DD>Build: <KBD><B>cd libburn_pykix ; ./bootstrap ; ./configure ; make</B>
<DD>Build: <KBD><B>cd libburn ; ./bootstrap ; ./configure --prefix /usr ; make ; cdrskin/compile_cdrskin.sh</B>
</KBD></DD>
<DD>Build of SVN versions needs <A HREF="http://sources.redhat.com/autobook/">
autotools</A> of at least version 1.7 installed.
@ -222,22 +297,29 @@ But after the run of <KBD>./bootstrap</KBD>, only
vanilla tools like make and gcc are needed.</DD>
</DD>
<DD>&nbsp;</DD>
<DT>The following downloads are intended for adventurous end users or
<DT>The following download is intended for adventurous end users or
admins with full system souvereignty.</DT>
<DD>Source (./bootstrap is already applied, build tested, for more see above
<DD>Source (./bootstrap is already applied, build tested, for more see
<A HREF="README_cdrskin_devel">upcoming README</A> ):
</DD>
<DD>
<A HREF="cdrskin-0.2.3.tar.gz">cdrskin-0.2.3.tar.gz</A>
(500 KB).
<A HREF="cdrskin-0.6.1.tar.gz">cdrskin-0.6.1.tar.gz</A>
(740 KB).
</DD>
<!-- This is not offered any more since spring 2008
<DT>The following downloads are intended for adventurous end users or
admins with full system souvereignty.</DT>
<DD>Binary (untar and move to /usr/bin/cdrskin):</DD>
<DD><A HREF="cdrskin_0.2.3-x86-suse9_0.tar.gz">
cdrskin_0.2.3-x86-suse9_0.tar.gz</A>, (60 KB).
<DD><A HREF="cdrskin_0.4.3-x86-suse9_0.tar.gz">
cdrskin_0.4.3-x86-suse9_0.tar.gz</A>, (110 KB).
</DD>
<DD><A HREF="cdrskin_0.2.3-x86-suse9_0-static.tar.gz">
cdrskin_0.2.3-x86-suse9_0-static.tar.gz</A>, (260 KB)
<DD><A HREF="cdrskin_0.4.3-x86-suse9_0-static.tar.gz">
cdrskin_0.4.3-x86-suse9_0-static.tar.gz</A>, (310 KB)
</DD>
-->
</DL>
</P>
@ -252,6 +334,10 @@ Historic versions based on Derek's and Ben's
<A HREF="http://icculus.org/burn">icculus.org/burn</A> :<BR>
<A HREF="cdrskin-0.1.2.0.2.ts.tar.gz">cdrskin-0.1.2.0.2.ts.tar.gz</A><BR>
<A HREF="cdrskin-0.1.3.0.2.ts.tar.gz">cdrskin-0.1.3.0.2.ts.tar.gz</A>
<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.
</P>
<HR>
@ -259,14 +345,33 @@ Historic versions based on Derek's and Ben's
<A NAME="examples">
<P>
<DL>
<DT>Example for a setup of device permissions. To be done by the superuser:</DT>
<DT>(CD devices which offer no r-permission are invisible to normal users.)</DT>
<DT>(CD devices which offer no w-permission are not useable.)</DT>
<DT>Example for a setup of device permissions.</DT>
<DT>
Newer Linux distros enable rw-access for the desktop user automatically.
So try as normal user whether all your drives are found.
CD devices which offer no rw-permission will stay invisible.
</DT>
<DD>$ <KBD><B>cdrskin --devices</B></KBD></DD>
<DT>If not all desired drives show up, become superuser and do again:</DT>
</DT>
<DD># <KBD><B>cdrskin --devices</B></KBD></DD>
<DD><KBD>...</KBD></DD>
<DD><KBD>0&nbsp; dev='/dev/sg0'&nbsp; rwrwr- :&nbsp; 'TEAC' 'CD-ROM CD-532S'</KBD></DD>
<DD><KBD>0&nbsp; dev='/dev/sr0'&nbsp; rwr-r- :&nbsp; 'TEAC' 'CD-ROM CD-532S'</KBD></DD>
<DD><KBD>1&nbsp; dev='/dev/hdc'&nbsp; rwrw-- :&nbsp; 'LITE-ON' 'LTR-48125S'</KBD></DD>
<DD># <KBD><B>chmod a+rw /dev/sg0 /dev/hdc</B></KBD></DD>
<DT>Most simple and most insecure is this equivalent
of the usual cdrecord permissions u+s,a+x:</DT>
<DD># <KBD><B>chmod a+rw /dev/sr0 /dev/hdc</B></KBD></DD>
<DT>
More secure is to put the permitted users into a group like
"floppy", to assign /dev/sr0 /dev/hdc to this group,
and to allow rw-access only to group members.
</DT>
<DD># <KBD><B>vi /etc/group</B></KBD></DD>
<DD><KBD>...</KBD></DD>
<DD><KBD>floppy:x:19:thomas,scdbackup</KBD></DD>
<DD><KBD>...</KBD></DD>
<DD># <KBD><B>chgrp floppy /dev/sr0 /dev/hdc</B></KBD></DD>
<DD># <KBD><B>chmod g+rw /dev/sr0 /dev/hdc</B></KBD></DD>
</DL>
</P>
@ -281,6 +386,8 @@ Example how to setup K3b to use cdrskin for burning data CD projects.
is a GUI frontend which uses cdrecord for CD burning.)
</P>
<!--
<HR>
<A NAME="scdbackup">
@ -288,37 +395,22 @@ is a GUI frontend which uses cdrecord for CD burning.)
<DL>
<DT>Example for a test session with a cdrecord based scdbackup installation:</DT>
<DD>$ <KBD><B>cdrskin -scanbus</B></KBD></DD>
<DD><KBD>...</KBD></DD>
<DD><KBD>scsibus1:</KBD></DD>
<DD><KBD>&nbsp;&nbsp;&nbsp; 1,0,0 &nbsp;&nbsp; 0)&nbsp; 'TEAC' 'CD-ROM CD-532S' '?' Removable CD-ROM</KBD></DD>
<DD><KBD>scsibus2:</KBD></DD>
<DD><KBD>&nbsp;&nbsp;&nbsp; 2,2,0 &nbsp;&nbsp; 1)&nbsp; 'LITE-ON' 'LTR-48125S' '?' Removable CD-ROM</KBD></DD>
<DD>$ <KBD><B>export SCDBACKUP_SCSI_ADR="2,2,0"</B></KBD></DD>
<!-- 0.2.4
<DD><KBD>...</KBD></DD>
<DD><KBD>&nbsp;&nbsp;&nbsp; 2,0,0 &nbsp;&nbsp; 0)&nbsp; 'TEAC' 'CD-ROM CD-532S' '?' Removable CD-ROM</KBD></DD>
<DD>$ <KBD><B>cdrskin -scanbus dev=ATA</B></KBD></DD>
<DD><KBD>...</KBD></DD>
<DD><KBD>&nbsp;&nbsp;&nbsp; 1,0,0 &nbsp;&nbsp; 1)&nbsp; 'LITE-ON' 'LTR-48125S' '?' Removable CD-ROM</KBD></DD>
<DD>$ <KBD><B>export SCDBACKUP_SCSI_ADR="ATA:1,0,0"</B></KBD></DD>
-->
<DD>$ <KBD><B>export SCDBACKUP_CDRECORD="cdrskin -v -v tao_to_sao_tsize=650m"</B></KBD></DD>
<DD>$ <KBD><B>export SCDBACKUP_CDRECORD="cdrskin -v -v"</B></KBD></DD>
<DD>$ <KBD><B>scdbackup_home</B></KBD></DD>
</DL>
<DL>
<DT>Example for a permanent configuration of cdrskin based scdbackup</DT>
<DD>$ <KBD><B>cd scdbackup-0.8.6/inst</B></KBD></DD>
<DD>$ <KBD><B>export SCDBACKUP_USE_CDRSKIN=1</B></KBD></DD>
<DD>$ <KBD><B>export SCDBACKUP_EJECT_ADR=/dev/cdrecorder</B></KBD></DD>
<DD>$ <KBD><B>./CONFIGURE_CD</B></KBD></DD>
<DD><KBD>...</KBD></DD>
<DD><KBD>cdrskin 0.2.2 : limited cdrecord compatibility wrapper for libburn</KBD></DD>
<DD><KBD>...</KBD></DD>
<DD><KBD> ------------------- SCSI devices. To be used like &nbsp;&nbsp; 0,0,0</KBD></DD>
<DD><KBD>cdrskin 0.3.8 : limited cdrecord compatibility wrapper for libburn</KBD></DD>
</DL>
If your system is stricken with some ill CD device then this can stall
and you will have to press <KBD>Ctrl+C</KBD> to abort.
@ -327,26 +419,18 @@ In this case, you may execute
and try again.
<DL>
<DT></DT>
<DD><KBD>&nbsp;&nbsp;&nbsp; 1,0,0 &nbsp;&nbsp; 0)&nbsp; 'TEAC' 'CD-ROM CD-532S' '?' Removable CD-ROM</KBD></DD>
<DD><KBD>&nbsp;&nbsp;&nbsp; 2,2,0 &nbsp;&nbsp; 1)&nbsp; 'LITE-ON' 'LTR-48125S' '?' Removable CD-ROM</KBD></DD>
<DD><KBD>------------------- end of SCSI device list</KBD></DD>
<!-- 0.2.4
<DD><KBD> ------------------- SCSI devices. To be used like &nbsp;&nbsp; 0,0,0</KBD></DD>
<DD><KBD>&nbsp;&nbsp;&nbsp; 2,0,0 &nbsp;&nbsp; 0)&nbsp; 'TEAC' 'CD-ROM CD-532S' '?' Removable CD-ROM</KBD></DD>
<DD><KBD> ------------------- end of SCSI device list</KBD></DD>
<DD><KBD> ------------------- ATA devices. To be used like ATA:0,0,0
<DD><KBD>&nbsp;&nbsp;&nbsp; 1,0,0 &nbsp;&nbsp; 1)&nbsp; 'LITE-ON' 'LTR-48125S' '?' Removable CD-ROM</KBD></DD>
-->
<DD><KBD>...</KBD></DD>
<DD><KBD>&nbsp;&nbsp;&nbsp; * Your cdrecord offers -driveropts=burnfree with your recorder.</KBD></DD>
<DD><KBD>...</KBD></DD>
<DD><KBD>scdbackup for CD 0.8.6 : First stage of installation done.</KBD></DD>
<DD><KBD>...</KBD></DD>
<DD><KBD>Now give it a try. Run : scdbackup_home</KBD></DD>
<DD>$ <KBD><B>unset SCDBACKUP_USE_CDRSKIN SCDBACKUP_EJECT_ADR</B></KBD></DD>
<DD>$ <KBD><B>unset SCDBACKUP_USE_CDRSKIN</B></KBD></DD>
</DL>
<DL>
<DT>To get back to using cdrecord :</DT>
@ -358,6 +442,8 @@ and try again.
</DL>
</P>
-->
<HR>
<A NAME="cdrecord">
@ -370,7 +456,7 @@ cdrecord but not vice versa.
I am a long time user of cdrecord and it works fine for me.
Especially i do appreciate its write mode -tao which allows to pipe arbitrary
data on CD and CD-RW via stdin. cdrecord is reliable, versatile and well
maintained. So for me - there would be not problem with it.
maintained. So for me - there would be no problem with it.
<BR>
But the author of cdrecord and the Linux kernel people foster a very hostile
relationship. Ok, that's their business, not mine (or ours if you are with me).
@ -384,10 +470,11 @@ the gestures necessary for their cdrecord applications.
Contact me. Let's see what we can achieve.
<BR>
<BR>
I am aware that libburn and cdrskin still have way to go until you can simply
install cdrskin as cdrecord and may expect any application to run with it.
Currently i do not encourage this approach, but of course such a replacement
opportunity is the long term goal of a cdrecord compatibility wrapper.
libburn and cdrskin are now mature enough to substitute cdrecord in its
major use cases of CD and DVD burning. It is possible to foist cdrskin on
various software packages if it gets falsely named "cdrecord".
I do not encourage this approach, but of course such a replacement
opportunity is the goal of a cdrecord compatibility wrapper.
<BR>
<BR>
It is very important to me that this project is not perceived as hostile
@ -401,6 +488,10 @@ I owe him much. For cdrecord, for mkisofs, for star. Chapeau.
<!-- <A NAME="bottom" HREF="main_ger.html#bottom">deutsch (german)</A>
<BR><BR>
-->
<A HREF="http://en.wikipedia.org/wiki/D%C3%B6ner_kebab">
<IMG SRC="doener_150x200_tr.png" BORDER=0
ALT="cdrskin logo: Doener mit Scharf"></A>
<BR><BR>
<FONT SIZE=+0>Enjoying free Open Source hosting by <A HREF="http://www.webframe.org">www.webframe.org</A><BR>
<A HREF="http://www.webframe.org">
<IMG SRC="msfree.gif" ALT="100 % Microsoft free" BORDER=0></A><BR>
@ -412,14 +503,25 @@ and by <A HREF="http://sourceforge.net">sourceforge.net</A><BR>
<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.
No mkisofs needed.
<DL>
<DD>
<A HREF="http://scdbackup.sourceforge.net/xorriso_eng.html">
(a second source of above)</A>
</DD>
</DL>
</DD>
<DD><A HREF=http://scdbackup.webframe.org/main_eng.html>
scdbackup, multi volume CD backup</A>
<DL><DD><A HREF=http://scdbackup.sourceforge.net/main_eng.html>
(a second source of above)</A></DL>
<DD><A HREF=http://stic.webframe.org>Some Tools for Image Collectors</A>
<DL><DD><A HREF=http://stic.sourceforge.net>(a second source of above)</A></DL>
(a second source of above)</A></DD></DL></DD>
<DD><A HREF=http://stic.sourceforge.net>Some Tools for Image Collectors</A>
</DD>
<DD><A HREF=http://scdbackup.webframe.org/pppoem>
pppoem, a DSL throughput monitor (mainly for Linux kernel 2.4)</A>
</DD>
</DL>
<BR><BR>
Legal statement: This website does not serve any commercial purpose.<BR>

View File

@ -1 +1 @@
#define Cdrskin_timestamP "2006.10.24.165610"
#define Cdrskin_timestamP "2009.01.07.140001"

File diff suppressed because it is too large Load Diff

View File

@ -23,31 +23,27 @@ typedef void (*sighandler_t)(int);
#include "cleanup.h"
#ifdef __FreeBSD__
#ifndef Cleanup_has_no_libburn_os_H
#include "../libburn/os.h"
/* see os.h for name of particular os-*.h where this is defined */
static int signal_list[]= { BURN_OS_SIGNAL_MACRO_LIST , -1};
static char *signal_name_list[]= { BURN_OS_SIGNAL_NAME_LIST , "@"};
static int signal_list_count= BURN_OS_SIGNAL_COUNT;
static int non_signal_list[]= { BURN_OS_NON_SIGNAL_MACRO_LIST, -1};
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 */
/* Signals to be caught */
static int signal_list[]= {
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT,
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM,
SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN,
SIGTTOU,
SIGBUS, SIGPROF, SIGSYS, SIGTRAP,
SIGVTALRM, SIGXCPU, SIGXFSZ, -1
};
static char *signal_name_list[]= {
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT",
"SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM",
"SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN",
"SIGTTOU",
"SIGBUS", "SIGPROF", "SIGSYS", "SIGTRAP",
"SIGVTALRM", "SIGXCPU", "SIGXFSZ", "@"
};
static int signal_list_count= 23;
#else /* __FreeBSD__ */
/* Signals to be caught */
static int signal_list[]= {
static int signal_list[]= {
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT,
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM,
SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN,
@ -55,7 +51,7 @@ static int signal_list[]= {
SIGBUS, SIGPOLL, SIGPROF, SIGSYS, SIGTRAP,
SIGVTALRM, SIGXCPU, SIGXFSZ, -1
};
static char *signal_name_list[]= {
static char *signal_name_list[]= {
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT",
"SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM",
"SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN",
@ -65,18 +61,21 @@ static char *signal_name_list[]= {
};
static int signal_list_count= 24;
#endif /* ! __FreeBSD__ */
/* Signals not to be caught */
static int non_signal_list[]= {
SIGKILL, SIGCHLD, SIGSTOP, SIGURG, -1
};
static int non_signal_list_count= 4;
SIGKILL, SIGCHLD, SIGSTOP, SIGURG, SIGWINCH, -1
};
static int non_signal_list_count= 5;
#endif /* Cleanup_has_no_libburn_os_H */
/* run time dynamic part */
static char cleanup_msg[4096]= {""};
static int cleanup_exiting= 0;
static int cleanup_has_reported= -1234567890;
static void *cleanup_app_handle= NULL;
static Cleanup_app_handler_T cleanup_app_handler= NULL;
@ -87,8 +86,10 @@ static int Cleanup_handler_exit(int exit_value, int signum, int flag)
{
int ret;
if(cleanup_msg[0]!=0)
if(cleanup_msg[0]!=0 && cleanup_has_reported!=signum) {
fprintf(stderr,"\n%s\n",cleanup_msg);
cleanup_has_reported= signum;
}
if(cleanup_perform_app_handler_first)
if(cleanup_app_handler!=NULL) {
ret= (*cleanup_app_handler)(cleanup_app_handle,signum,0);

View File

@ -1,12 +1,13 @@
#!/bin/sh
# compile_cdrskin.sh
# Copyright 2005 - 2006 Thomas Schmitt, scdbackup@gmx.net, GPL
# Copyright 2005 - 2008 Thomas Schmitt, scdbackup@gmx.net, GPL version 2
# to be executed within ./libburn-* resp ./cdrskin-*
debug_opts=
debug_opts="-O2"
def_opts=
libvers="-DCdrskin_libburn_0_2_3"
largefile_opts="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1"
libvers="-DCdrskin_libburn_0_6_0"
cleanup_src_or_obj="libburn/cleanup.o"
libdax_msgs_o="libburn/libdax_msgs.o"
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
@ -31,16 +32,16 @@ do
libvers="-DCdrskin_libburn_cvs_A60220_tS"
libdax_audioxtr_o=
libdax_msgs_o="libburn/message.o"
cleanup_src_or_obj="cdrskin/cleanup.c"
elif test "$i" = "-libburn_0_2_2"
cleanup_src_or_obj="-DCleanup_has_no_libburn_os_H cdrskin/cleanup.c"
elif test "$i" = "-libburn_0_6_0"
then
libvers="-DCdrskin_libburn_0_2_2"
libdax_audioxtr_o=
libdax_msgs_o="libburn/message.o"
cleanup_src_or_obj="cdrskin/cleanup.c"
elif test "$i" = "-libburn_0_2_3"
libvers="-DCdrskin_libburn_0_6_0"
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
libdax_msgs_o="libburn/libdax_msgs.o"
cleanup_src_or_obj="libburn/cleanup.o"
elif test "$i" = "-libburn_svn"
then
libvers="-DCdrskin_libburn_0_2_3"
libvers="-DCdrskin_libburn_0_6_1"
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
libdax_msgs_o="libburn/libdax_msgs.o"
cleanup_src_or_obj="libburn/cleanup.o"
@ -50,6 +51,10 @@ do
elif test "$i" = "-oldfashioned"
then
def_opts="$def_opts -DCdrskin_oldfashioned_api_usE"
cleanup_src_or_obj="-DCleanup_has_no_libburn_os_H cdrskin/cleanup.c"
elif test "$i" = "-no_largefile"
then
largefile_opts=
elif test "$i" = "-do_not_compile_cdrskin"
then
compile_cdrskin=0
@ -63,10 +68,7 @@ do
do_strip=1
elif test "$i" = "-g"
then
debug_opts="$debug_opts -g"
elif test "$i" = "-O2"
then
debug_opts="$debug_opts -O2"
debug_opts="-g"
elif test "$i" = "-help" -o "$i" = "--help" -o "$i" = "-h"
then
echo "cdrskin/compile_cdrskin.sh : to be executed within top level directory"
@ -74,15 +76,15 @@ do
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_2_2 set macro to match libburn-0.2.2."
echo " -libburn_0_2_3 set macro to match current libburn-SVN."
echo " -libburn_0_6_0 set macro to match libburn-0.6.0"
echo " -libburn_svn set macro to match current libburn-SVN."
echo " -no_largefile do not use 64 bit off_t (must match libburn)."
echo " -do_not_compile_cdrskin omit compilation of cdrskin/cdrskin."
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."
echo " -do_strip apply program strip to compiled programs."
echo " -g compile with cc option -g."
echo " -O2 compile with cc option -O2."
echo " -g produce debuggable programm."
echo " -static compile with cc option -static."
exit 0
elif test "$i" = "-static"
@ -99,7 +101,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"
cc $warn_opts -I. $static_opts $debug_opts $libvers $def_opts \
cc -I. \
$warn_opts \
$static_opts \
$debug_opts \
$libvers \
$largefile_opts \
$def_opts \
\
-DCdrskin_build_timestamP='"'"$timestamp"'"' \
\
-o cdrskin/cdrskin \
@ -120,6 +129,7 @@ then
\
libburn/sg.o \
libburn/write.o \
libburn/read.o \
$libdax_audioxtr_o \
$libdax_msgs_o \
\

78
cdrskin/convert_man_to_html.sh Executable file
View File

@ -0,0 +1,78 @@
#!/bin/sh
#
# convert_man_to_html.sh - ts A61214
#
# Generates a HTML version of man page cdrskin.1
#
# To be executed within the libburn toplevel directory (like ./libburn-0.2.7)
#
# set -x
man_dir=$(pwd)"/cdrskin"
export MANPATH="$man_dir"
manpage="cdrskin"
raw_html=$(pwd)/"cdrskin/raw_man_1_cdrskin.html"
htmlpage=$(pwd)/"cdrskin/man_1_cdrskin.html"
if test -r "$man_dir"/"$manpage".1
then
dummy=dummy
else
echo "Cannot find readable man page source $1" >&2
exit 1
fi
if test -e "$man_dir"/man1
then
dummy=dummy
else
ln -s . "$man_dir"/man1
fi
if test "$1" = "-work_as_filter"
then
# set -x
sed \
-e 's/<meta name="generator" content="groff -Thtml, see www.gnu.org">/<meta name="generator" content="groff -Thtml, via man -H, via cdrskin\/convert_man_to_html.sh">/' \
-e 's/<meta name="Content-Style" content="text\/css">/<meta name="Content-Style" content="text\/css"><META NAME="description" CONTENT="man page of cdrskin"><META NAME="keywords" CONTENT="man cdrskin, manual, cdrskin, CD, CD-RW, CD-R, burning, cdrecord, compatible"><META NAME="robots" CONTENT="follow">/' \
-e 's/<title>CDRSKIN<\/title>/<title>man 1 cdrskin<\/title>/' \
-e 's/<h1 align=center>CDRSKIN<\/h1>/<h1 align=center>man 1 cdrskin<\/h1>/' \
-e 's/<body>/<body BGCOLOR="#F5DEB3" TEXT=#000000 LINK=#0000A0 VLINK=#800000>/' \
-e 's/<b>Overview of features:<\/b>/\&nbsp;<BR><b>Overview of features:<\/b>/' \
-e 's/<b>General information paragraphs:<\/b>/\&nbsp;<BR><b>General information paragraphs:<\/b>/' \
-e 's/<b>Track recording model:<\/b>/\&nbsp;<BR><b>Track recording model:<\/b>/' \
-e 's/^In general there are two types of tracks: data and audio./\&nbsp;<BR>In general there are two types of tracks: data and audio./' \
-e 's/^While audio tracks just contain a given/\&nbsp;<BR>While audio tracks just contain a given/' \
-e 's/<b>Write mode selection:<\/b>/\&nbsp;<BR><b>Write mode selection:<\/b>/' \
-e 's/<b>Recordable CD Media:<\/b>/\&nbsp;<BR><b>Recordable CD Media:<\/b>/' \
-e 's/<b>Overwriteable DVD Media:<\/b>/\&nbsp;<BR><b>Overwriteable DVD Media:<\/b>/' \
-e 's/<b>Sequentially Recordable DVD Media:<\/b>/\&nbsp;<BR><b>Sequentially Recordable DVD Media:<\/b>/' \
-e 's/^The write modes for DVD+R/\&nbsp;<BR>The write modes for DVD+R/' \
-e 's/<b>Drive preparation and addressing:<\/b>/\&nbsp;<BR><b>Drive preparation and addressing:<\/b>/' \
-e 's/^If you only got one CD capable drive/\&nbsp;<BR>If you only got one CD capable drive/' \
-e 's/<b>Emulated drives:<\/b>/\&nbsp;<BR><b>Emulated drives:<\/b>/' \
-e 's/^Alphabetical list of options/\&nbsp;<BR>Alphabetical list of options/' \
-e 's/<\/body>/<BR><HR><FONT SIZE=-1><CENTER>(HTML generated from '"$manpage"'.1 on '"$(date)"' by '$(basename "$0")' )<\/CENTER><\/FONT><\/body>/' \
-e 's/See section FILES/See section <A HREF="#FILES">FILES<\/A>/' \
-e 's/See section EXAMPLES/See section <A HREF="#EXAMPLES">EXAMPLES<\/A>/' \
<"$2" >"$htmlpage"
set +x
chmod u+rw,go+r,go-w "$htmlpage"
echo "Emerged file:"
ls -lL "$htmlpage"
else
export BROWSER='cp "%s" '"$raw_html"
man -H "$manpage"
"$0" -work_as_filter "$raw_html"
rm "$raw_html"
rm "$man_dir"/man1
fi

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

After

Width:  |  Height:  |  Size: 9.2 KiB

View File

@ -1,54 +1,62 @@
--------------------------------------------------------------------------
cdrskin Wiki - plain text copy
--------------------------------------------------------------------------
[[Image(source:/libburn/trunk/cdrskin/doener_150x200_tr.png)]] [http://en.wikipedia.org/wiki/D%C3%B6ner_kebab Doener]
cdrskin-0.2.3 is the cdrecord compatibility middleware of libburn.
'''cdrskin is the cdrecord compatibility middleware of libburn.'''
Its paragon, 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. Currently it does CD-R and CD-RW.
Its future ability to burn DVD media depends on the development of libburn.
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, 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.
Many bytes have been copied from the message output of cdrecord
runs, though. The most comprehensive technical overview of cdrskin
can be found in cdrskin/README .
can be found in [http://libburnia-project.org/browser/libburn/trunk/cdrskin/README?format=txt cdrskin/README].
About libburn API for burning CD and DVD: http://api.libburnia-project.org
--------------------------------------------------------------------------
cdrskin with CD media fails to match its paragon cdrecord on two major
fields: convenient TAO burn mode and multi session.
cdrskin does not provide DVD burning yet. See advise to use dvd+rw-tools
at the end of this text.
For yet unsupported media types see the advice to use dvd+rw-tools at
the end of this text.
--------------------------------------------------------------------------
About the command line options of cdrskin:
They are described in detail in [http://scdbackup.sourceforge.net/man_1_cdrskin_devel.html#OPTIONS section OPTIONS] of
[http://scdbackup.sourceforge.net/man_1_cdrskin_devel.html man cdrskin]
There are two families of options: cdrecord-compatible ones and options
which are specific to cdrskin. The latter are mostly used to configure
cdrskin for its task to emulate cdrecord. There are some, nevertheless,
which provide rather exotic unique features of cdrskin.
The cdrecord-compatible options are listed in the output of
{{{
cdrskin -help
}}}
where the option "help" has *one* dash. Online: [http://scdbackup.sourceforge.net/cdrskin_help_devel cdrskin -help]
where the option "help" has *one* dash.
For these options you may expect program behavior that is roughly the
same as described in original man 1 cdrecord .
same as described in original man cdrecord .
Online: http://cdrecord.berlios.de/old/private/man/cdrecord-2.0.html
The cdrskin-specific options are listed by
{{{
cdrskin --help
}}}
where the option "help" has *two* dashes. Online: [http://scdbackup.sourceforge.net/cdrskin__help_devel cdrskin --help]
where the option "help" has *two* dashes.
Those have no man page yet. Some are very experimental and should only be
used in coordination with the libburn developer team.
Some are very experimental and should only be
used in coordination with the libburnia developer team.
Some are of general user interest, though:
--------------------------------------------------------------------------
@ -56,11 +64,10 @@ Some are of general user interest, though:
--devices allows the sysadmin to scan the system for possible drives
and displays their detected properties.
The drives are listed one per line, with fields:
libburn-drive-number sysadmin-device-file permissions : vendor type
0 dev='/dev/sg0' rwrw-- : 'HL-DT-ST' 'DVDRAM GSA-4082B'
libburn-drive-number, sysadmin-device-file, permissions, vendor, type
{{{
0 dev='/dev/sr0' rwrw-- : 'HL-DT-ST' 'DVDRAM GSA-4082B'
}}}
This feature is valuable since cdrskin -scanbus will not give you
the device file name and its current permissions.
cdrskin will accept of course the proposed dev= option as address
@ -74,7 +81,121 @@ has to offer both, r- and w-permission.
--------------------------------------------------------------------------
--fifo_start_empty is a throughput enhancer for unsteady data streams
blank=as_needed applies the suitable blanking or formatting to make
any supported type of media ready for writing from scratch.
If this is not possible, e.g. because the media is written and not
re-usable, then the program run fails.
Option blank= offers several specialized blanking and formatting types,
which one may use for particular purposes on DVD-RW, DVD-RAM and BD-RE.
(See also below: blank=format_overwrite)
The drive offers a list of possible formats by cdrskin option --list_formats.
One should aquire MMC background information before making use of them.
--------------------------------------------------------------------------
cdrskin does not only read from and write to optical drives which comply
to the MMC standard but also does the same with regular files or block
devices other than optical drives.
Because the power to alter a disk file might be a bad surprise for a
traditional user of cdrecord, it is necessary to give option
--allow_emulated_drives before an emulated drive may be addressed.
Eventually one of the startup files would be a good place for it.
See man page, section FILES.
The addresses of emulated drives begin with the prefix "stdio:".
{{{
dev=stdio:/tmp/pseudo_drive
dev=stdio:/dev/usbstick
}}}
Regular files and block devices behave much like DVD-RAM.
Other file types may be valid targets for write-only operations.
This includes standard output, named pipes, character devices
{{{
dev=stdio:/dev/fd/1
dev=stdio:/tmp/named_pipe
dev=stdio:/dev/ptyxy
}}}
These files behave much like blank DVD-R.
All files used as pseudo-drives have to offer rw-permission.
--------------------------------------------------------------------------
The DVD capabilities of cdrskin differ from those of cdrecord-ProDVD. cdrskin
offers TAO-like multi-session with DVD-R[W], DVD+R[ DL] and TAO-like single
session with overwriteable DVD media. It also offers DAO on DVD-R[W] which is
probably the same as the traditional cdrecord-ProDVD write mode.
Non-cdrecord blank mode blank=format_overwrite brings a DVD-RW
disc from its initial profile "Sequential Recording" into profile state
"Restricted Overwrite".
{{{
cdrskin dev=/dev/sr0 -v blank=format_overwrite
}}}
DVD-RAM, DVD+RW, BD-RE and overwriteable DVD-RW appear to cdrskin as blank
media which are capable of taking only a single track. This track may be
positioned on a 32KiB aligned address, though.
{{{
cdrskin ... write_start_address=2412m ...
}}}
Non-cdrecord blank mode blank=deformat_sequential brings an overwriteable
DVD-RW back into state "Sequential Recording" with the capability of doing
multi-session, if the drive is capable of "Incremental Streaming"
(MMC feature 21h).
Used sequential DVD-RW media may be blanked by blank=fast or blank=all which
normally both do full blanking. Thus sequential DVD-RW behave much like large
CD-RW with possibly more than 99 tracks.
blank=deformat_sequential does minimal blanking of DVD-RW which usually yields
media incapable of "Incremental Streaming".
Option --prodvd_cli_compatible activates blank=fast and blank=all for
overwriteable DVD-RW which normally ignore those two options. It also makes
option -multi tolerable with media and write modes which are not suitable for
multi-session. (The default behavior of cdrskin deems me to be preferrable.)
Option --grow_overwriteable_iso gives cdrskin ISO pseudo-multi-session
capabilities on DVD-RAM, DVD+RW, BD-RE similar to growisofs.
Associated options blank=, -multi, -msinfo and -toc are available in this case.
They either pretend a blank media (if there is no ISO 9660 image) or appendable
media with a single session and track on it. blank= invalidates ISO images.
--------------------------------------------------------------------------
assert_write_lba=<lba> allows to ensure that the start block address which
was used with the formatter program (e.g. mkisofs -C) matches the start block
address which will be used by the upcoming burn.
E.g. cdrskin aborts with an error message if
{{{
assert_write_lba=0
}}}
is given but an appendable media is to be burned which would start at
block 68432.
An ISO-9660 file system image must be prepared according to a particular
block address on media. If the prepared address and the real address on media
do not match then the filesystem will not be mountable or may even cause system
trouble.
A sequential archive format like afio or star will not necessarily need such
a coordination of addresses. It might nevertheless be confusing to a reader
if the archive does not start at block 0.
--------------------------------------------------------------------------
fifo_start_at=<num> is a throughput enhancer for unsteady data streams
like they are produced by a compressing archiver program when piping to
CD on-the-fly. It makes better use of the general property of a FIFO
buffer to transport surplus bandwidth into the future. Yep. A time machine.
@ -98,10 +219,16 @@ underruns, of course.
With a very fat fs=# buffer (128 MB for 12x CD is not unrealistic) this
can cause a big delay until burning finally starts and takes its due time.
--fifo_start_empty makes cdrskin start burning without waiting for the
FIFO to be full resp. the data stream to end. It can make use of the
seconds spend with drive preparation and lead-in, it risks a few drive
buffer underruns at the beginning of burn - but modern drives stand this.
fifo_start_at=<num> makes cdrskin start burning after the given number of bytes
is read rather than waiting for the FIFO to be completely full resp. the data
stream to end. It risks a few drive buffer underruns at the beginning of burn
- but modern drives stand this.
Usage examples:
{{{
cdrskin ... fs=128m fifo_start_at=20m ...
cdrskin ... fifo_start_at=0 ...
}}}
Note: no FIFO can give you better average throughput than the average
throughput of the data source and the throughput of the burner.
@ -117,21 +244,12 @@ default settings of cdrskin. Possible locations for such settings:
/etc/opt/cdrskin/rc
/etc/cdrskin/cdrskin.conf
$HOME/.cdrskinrc
--------------------------------------------------------------------------
tao_to_sao_tsize=<num> allows the - actually unsupported - cdrecord option
-tao and defines a default track size to be used if - as custom with -tao -
no option tsize=# is given.
As in general with cdrskin tsize=# the data source does not have to provide
the full annouced amount of data. Missing data will be padded up by 0-bytes.
Surplus data is supposed to cause an error, though. The burn will then
be a failure in any way.
--------------------------------------------------------------------------
dev_translation=<sep><from><sep><to> may be needed to foist cdrskin to
frontend programs of cdrecord which do *not* ask cdrecord -scanbus but
which make own assumptions and guesses about cdrecord's device addresses.
@ -147,15 +265,15 @@ cdrskin the necessary hint.
Example: Your frontend insists in using "0,0,0" and --devices reported
dev='/dev/hdc' resp. cdrskin dev=ATA -scanbus reported "1,0,0" then this
would be the appropriate translation:
{{{
dev_translation=+0,0,0+/dev/hdc
}}}
The "+" character is a separator to be choosen by you.
Currently i am not aware of the need to choose any other than "+"
unless you get playful with custom translations like
{{{
dev_translation=-"cd+dvd"-1,0,0
}}}
See http://scdbackup.sourceforge.net/k3b_on_cdrskin.html
for an illustrated example with K3b 0.10 .
@ -163,9 +281,10 @@ for an illustrated example with K3b 0.10 .
DVD advise:
For burning of DVD media the cdrskin project currently advises to use
Andy Polyakov's dvd+rw-tools which despite their historic name burn
for me on above burner: DVD+RW, DVD+R, DVD-RW, DVD-R .
For burning of DVD/BD media other than DVD-RAM, DVD+RW, DVD+R, DVD+R DL,
DVD-RW, DVD-R, BD-RE, the cdrskin project currently advises to use
Andy Polyakov's dvd+rw-tools which despite their historic name are
capable of all the media above and more, including BD discs.
http://fy.chalmers.se/~appro/linux/DVD+RW/tools
@ -173,24 +292,27 @@ They are not compatible or related to cdrecord resp. cdrecord-ProDVD
(now obsoleted by original source cdrtools cdrecord with identical
capabilities besides the license key).
If there is sincere and well motivated interest, the cdrskin project could try
to employ growisofs as DVD burning engine. The cdrskin project would prefer to
wait for DVD support being included in libburn, though.
A very limited and specialized cdrecord-compatibility wrapper for growisofs
serves in my project scdbackup. It is not overly hard to make one that serves
some very few fixed use cases.
To my knowledge, Linux kernels 2.6 do write to DVD+RW via block devices as
they would write to a traditional tape device. Try old tape archiver
commands with addresses like /dev/sr0 or /dev/hdc rather than /dev/mt0 .
I have heard rumors that DVD-RW in mode "restricted overwrite" would be
block device ready, too. My burner is not a real friend of DVD-RW and
in an experiment the burn worked fine - but the result was not identical
to the stream sent to the device. I had similar failure with DVD-RAM, too.
Beware of the impact of a slow block device on overall system i/o buffering.
It is wise to curb its input to a speed which it is able to deliver to media.
Else your i/o dedicated RAM might buffer a big amount of stream data.
--------------------------------------------------------------------------
Advanced multi-session use cases:
A special feature of dvd+rw-tools is growing of ISO-9660 filesystems on
overwriteable media. This is not the same as multi-session writing of cdrskin
with CD media, but retrieves additional information from the existing ISO
image and finally manipulates the start sectors of this existing image.
So, inspired by growisofs, cdrskin can offer DVD multi-session not only with
sequential DVD-R[W] and with DVD+R [DL], but also with DVD-RAM, DVD+RW, BD-RE
and even regular disk files or block devices other than CD/DVD writers.
This is enabled by option --grow_overwriteable_iso.
The libburnia project provides an integrated ISO-9660 multi-session tool
named [wiki:Xorriso xorriso] which tries to go one step beyond
growisofs. It uses [wiki:Libburn libburn] , [wiki:Libisofs libisofs]
and [wiki:Libisoburn libisoburn].
See [http://scdbackup.sourceforge.net/man_1_xorriso.html man xorriso].
--------------------------------------------------------------------------

View File

@ -1,4 +1,4 @@
AC_INIT([libburn], [0.2.3], [http://libburn.pykix.org])
AC_INIT([libburn], [0.6.0], [http://libburnia-project.org])
AC_PREREQ([2.50])
dnl AC_CONFIG_HEADER([config.h])
@ -7,37 +7,113 @@ AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE([subdir-objects])
AM_CONFIG_HEADER(config.h)
dnl Making releases:
dnl BURN_MICRO_VERSION += 1;
dnl BURN_INTERFACE_AGE += 1;
dnl BURN_BINARY_AGE += 1;
dnl if any functions have been added, set BURN_INTERFACE_AGE to 0.
dnl if backwards compatibility has been broken,
dnl set BURN_BINARY_AGE and BURN_INTERFACE_AGE to 0.
dnl Notes by ts A71207 - A81111 :
dnl
dnl if MAJOR or MINOR version changes, be sure to change AC_INIT above to match
dnl Regrettably the meaning of the various version types was misunderstood
dnl before version 0.4.1.
dnl
dnl In the past MAJOR.MINOR.MICRO versions led to the following SONAME numbers:
dnl 0.2.2 = 2 , 0.2.3 = 3 , 0.2.6 = 6
dnl 0.3.0 = 0 , 0.3.2 = 2 , 0.3.4 = 4 . 0.3.6 = 6 , 0.3.8 = 4
dnl 0.4.0 = 0 (also released as SONAME 4)
dnl
dnl Meanwhile the following schemes are maintained in parallel:
dnl
dnl BURN_MAJOR_VERSION , BURN_MINOR_VERSION , BURN_MICRO_VERSION
dnl are three small non-negative integers which describe the evolution
dnl steps of the library.
dnl Older applications are able to use younger libraries over
dnl quite a long range of such steps. Some day, nevertheless,
dnl compatibility might get terminated, after due notice.
dnl
dnl SONAME (libburn.so.4)
dnl is a small positive integer which marks a family of compatible
dnl evolution steps. Libraries with a particular SONAME allow a binary
dnl with the same SONAME to start up. Any further compatibility check is to
dnl be done by own runtime means. Especially *_version() calls in the API
dnl which return BURN_MAJOR_VERSION, BURN_MINOR_VERSION, BURN_MICRO_VERSION.
dnl See below.
dnl
dnl CURRENT, AGE, REVISION
dnl are three integers used by libtool. CURRENT is positive, the others
dnl non-negative. The use at runtime is not known yet. But libtool computes
dnl at build time SONAME = CURRENT - AGE.
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 In the terminology of this file:
dnl CURRENT = LT_CURRENT
dnl AGE = LT_AGE
dnl REVISION= LT_REVISION
dnl
dnl Beginning with libburn-0.4.1 a rectified counting was introduced as
dnl CURRENT=10, REVISION=1, AGE=6
dnl This rectification declared that version to be binary compatible up
dnl from libburn-0.3.4.
dnl Real compatibility was given since libburn-0.3.2.
dnl Beware of libburn-0.2.6 which had SONAME=6 and is not binary compatible.
dnl Applications for libburn-0.2 to libburn-0.3.1 need recompilation but no
dnl source code changes.
dnl
dnl Neatly versioned stable releases meanwhile:
dnl 0.4.2 = libburn.so.4.7.0
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
dnl So LT_CURRENT, LT_REVISION and LT_AGE get set directly here.
dnl SONAME of the emerging library is LT_CURRENT - LT_AGE.
dnl The linker will do no finer checks. Especially no age range check for
dnl the application binary. If SONAME matches, then the couple starts.
dnl
dnl Therefore at run time info is provided by libburn function burn_version().
dnl It returns the major, minor and micro revision of the library.
dnl Before using any API feature, a program should check for age.
dnl
dnl The variables BURN_*_VERSION are mere copies for informing libtool.
dnl The true values which get issued and should be compared are macros
dnl defined in libburn/libburn.h .
dnl
dnl Normally one can allow a program to run with a library which passed the
dnl linker SONAME test and which is not older than the library it was
dnl developed for. Library2 is younger than library1 if:
dnl major2>major1 || (major2==major1 &&
dnl (minor2>minor1 || (minor2==minor1 && micro2 > micro1)))
dnl
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=2
BURN_MICRO_VERSION=3
BURN_INTERFACE_AGE=0
BURN_BINARY_AGE=0
BURN_MINOR_VERSION=6
BURN_MICRO_VERSION=0
BURN_VERSION=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION
AC_SUBST(BURN_MAJOR_VERSION)
AC_SUBST(BURN_MINOR_VERSION)
AC_SUBST(BURN_MICRO_VERSION)
AC_SUBST(BURN_INTERFACE_AGE)
AC_SUBST(BURN_BINARY_AGE)
AC_SUBST(BURN_VERSION)
dnl Libtool versioning
LT_RELEASE=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION
LT_CURRENT=`expr $BURN_MICRO_VERSION - $BURN_INTERFACE_AGE`
LT_REVISION=$BURN_INTERFACE_AGE
LT_AGE=`expr $BURN_BINARY_AGE - $BURN_INTERFACE_AGE`
LT_RELEASE=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION
dnl
dnl ts A90102
dnl This is the release version libburn-0.6.0 = libburn.so.4.25.0
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 = 29 - 25 = 4 . Library name = libburn.so.4.25.0
LT_CURRENT=29
LT_AGE=25
LT_REVISION=0
LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
AC_SUBST(LT_RELEASE)
@ -46,6 +122,12 @@ AC_SUBST(LT_REVISION)
AC_SUBST(LT_AGE)
AC_SUBST(LT_CURRENT_MINUS_AGE)
dnl ts A71207: This is done only not to break any old components
BURN_INTERFACE_AGE=$LT_REVISION
BURN_BINARY_AGE=`expr $LT_AGE + $BURN_INTERFACE_AGE`
AC_SUBST(BURN_INTERFACE_AGE)
AC_SUBST(BURN_BINARY_AGE)
AC_PREFIX_DEFAULT([/usr/local])
test "$prefix" = "NONE" && prefix=$ac_default_prefix
@ -59,6 +141,7 @@ AC_C_BIGENDIAN
dnl Large file support
AC_SYS_LARGEFILE
AC_FUNC_FSEEKO
AC_CHECK_FUNC([fseeko])
if test ! $ac_cv_func_fseeko; then
AC_ERROR([Libburn requires largefile support.])
fi
@ -71,12 +154,6 @@ AC_PROG_INSTALL
AC_CHECK_HEADERS()
AC_CHECK_MEMBER([struct tm.tm_gmtoff],
[AC_DEFINE(HAVE_TM_GMTOFF, 1,
[Define this if tm structure includes a tm_gmtoff entry.])],
,
[#include <time.h>])
THREAD_LIBS=-lpthread
AC_SUBST(THREAD_LIBS)
@ -108,6 +185,5 @@ AC_CONFIG_FILES([
doc/doxygen.conf
version.h
libburn-1.pc
libisofs-1.pc
])
AC_OUTPUT

View File

@ -5,61 +5,47 @@
@section intro Introduction
Libburn is an open-source library for reading, mastering and writing
optical discs. For now this means only CD-R and CD-RW.
Libburnia is an open-source project for reading, mastering and writing
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-R, BD-RE.
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.
Not supported yet are DVD-R/DL. Testers wanted.
Our scope is currently Linux 2.4 and 2.6 and we will have a hard time to widen
this for now, because of our history. The project could need advise from or
membership of skilled kernel people and people who know how to talk CD/DVD
drives into doing things.
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.
We do have a workable code base for burning data CDs, though. The burn API is
quite comprehensively documented and can be used to build a presentable
application.
We do have a functional binary which emulates parts 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.
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.
@subsection components The project components (list subject to growth, hopefully):
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.
- 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/hdX (e.g. on kernel 2.6).
libburn is the foundation of our cdrecord emulation.
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.
- 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.
- 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.
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.
- "test" is a collection of application gestures and examples given by the
authors of the library features. The main API example of libburn
is named test/libburner.c .
Explore these examples if you look for inspiration.
We plan to be a responsive upstream. Bear with us.
SONAME:
libburn.so.4 (since 0.3.4, March 2007),
@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)
@ -71,49 +57,59 @@ 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://libburn.pykix.org .
It can list the available devices, can blank a CD-RW and
can burn to CD-R or CD-RW.
(see: libburn/libburn.h) as provided on http://libburnia-project.org .
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 libburn 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.
to serve the libburnia team as reference application. libburner does indeed
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>|"-"]
[--blank_fast|--blank_full] [--audio]
[--try_to_simulate] [--stdin_size <bytes>]
[<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 -
Burn a file to drive chosen by number:
test/libburner --drive 0 my_image_file
Burn a file to drive chosen by persistent address:
Burn a file to drive chosen by number, leave appendable:
test/libburner --drive 0 --multi my_image_file
Burn a file to drive chosen by persistent address, close:
test/libburner --drive /dev/hdc my_image_file
Blank a used CD-RW (is combinable with burning in one run):
test/libburner --drive /dev/hdc --blank_fast
Burn two audio tracks
Blank a used DVD-RW (is combinable with burning in one run):
test/libburner --drive /dev/hdc --blank_full
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
test/libburner --drive /dev/hdc --audio track1.cd track2.cd
Burn a compressed afio archive on-the-fly, pad up to 700 MB:
Burn a compressed afio archive on-the-fly:
( cd my_directory ; find . -print | afio -oZ - ) | \
test/libburner --drive /dev/hdc --stdin_size 734003200 -
To be read from *not mounted* CD via: afio -tvZ /dev/hdc
Program tar would need a clean EOF which our padded CD cannot deliver.
test/libburner --drive /dev/hdc -
To be read from *not mounted* media via: afio -tvZ /dev/hdc
</pre>
libburner has two companions, telltoc and dewav, which help to perform some
peripheral tasks of burning.
telltoc prints a table of content (sessions, tracks and leadouts), it tells
about type and state of media, and also is able to provide the necessary
multi-session information for program mkisofs option -C. Especially helpful
are its predictions with "Write multi" and "Write modes" where availability
of "TAO" indicates that tracks of unpredicted length can be written.
See: test/telltoc --help.
dewav extracts raw byte-swapped audio data from files of format .wav (MS WAVE)
or .au (SUN Audio). See example in libburner --help.
@subsection libburner-source Sourceode of libburner

View File

@ -1,121 +0,0 @@
/**
@author Mario Danic, Thomas Schmitt
@mainpage Libburn Documentation Index
@section intro Introduction
Libburn is an open-source library for reading, mastering and writing
optical discs. For now this means only CD-R and CD-RW.
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 and we will have a hard time to widen
this for now, because of our history. The project could need advise from or
membership of skilled kernel people and people who know how to talk CD/DVD
drives into doing things.
We do have a workable code base for burning data CDs, though. The burn API is
quite comprehensively documented and can be used to build a presentable
application.
We do have a functional binary which emulates parts 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.
@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/hdX (e.g. on kernel 2.6).
libburn is the foundation of our cdrecord emulation.
- 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.
- 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.
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.
- "test" is a collection of application gestures and examples given by the
authors of the library features. The main API example of libburn
is named test/libburner.c .
Explore these examples if you look for inspiration.
We plan to be a responsive upstream. Bear with us.
@section using Using the libraries
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
- ./bootstrap (needed if you downloaded from SVN)
- ./configure
- make
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://libburn.pykix.org .
It can list the available devices, can blank a CD-RW and
can burn to CD-R or CD-RW.
It's main purpose, nevertheless, is to show you how to use libburn and also
to serve the libburn 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.
@subsection libburner-help Libburner --help
<pre>
Usage: test/libburner
[--drive <address>|<driveno>|"-"]
[--verbose <level>] [--blank_fast|--blank_full]
[--burn_for_real|--try_to_simulate] [--stdin_size <bytes>]
[<imagefile>|"-"]
Examples
A bus scan (needs rw-permissions to see a drive):
test/libburner --drive -
Burn a file to drive chosen by number:
test/libburner --drive 0 --burn_for_real my_image_file
Burn a file to drive chosen by persistent address:
test/libburner --drive /dev/hdc --burn_for_real my_image_file
Blank a used CD-RW (is combinable with burning in one run):
test/libburner --drive 0 --blank_fast
Burn a compressed afio archive on-the-fly, pad up to 700 MB:
( cd my_directory ; find . -print | afio -oZ - ) | \
test/libburner --drive /dev/hdc --burn_for_real --stdin_size 734003200 -
To be read from *not mounted* CD via:
afio -tvZ /dev/hdc
Program tar would need a clean EOF which our padded CD cannot deliver.
</pre>
@subsection libburner-source Sourceode of libburner
Click on blue names of functions, structures, variables, etc in oder to
get to the according specs of libburn API or libburner sourcecode.
@include libburner.c
*/

1275
doc/cookbook.txt Normal file

File diff suppressed because it is too large Load Diff

388
doc/ddlp.txt Normal file
View File

@ -0,0 +1,388 @@
-------------------------------------------------------------------------------
Users of modern desktop Linux installations report misburns with CD/DVD
recording due to concurrency problems.
This text describes two locking protocols which have been developed by our
best possible effort. But finally they rather serve as repelling example of
what would be needed in user space to achieve an insufficient partial solution.
Ted Ts'o was so friendly to help as critic with his own use cases. It turned
out that we cannot imagine a way in user space how to cover reliably the needs
of callers of libblkid and the needs of our burn programs.
-------------------------------------------------------------------------------
Content:
The "Delicate Device Locking Protocol" shall demonstrate our sincere
consideration of the problem.
"What are the Stumble Stones ?" lists reasons why the effort finally failed.
-----------------------------------------------------------------------------
Delicate Device Locking Protocol
(a joint sub project of cdrkit and libburnia)
(contact: scdbackup@gmx.net )
Our projects provide programs which allow recording of data on CD or DVD.
We encounter an increasing number of bug reports about spoiled burn runs and
wasted media which obviously have one common cause: interference by other
programs which access the drive's device files.
There is some riddling about which gestures exactly are dangerous for
ongoing recordings or can cause weirdly misformatted drive replies to MMC
commands.
We do know, nevertheless, that these effects do not occur if no other program
accesses a device file of the drive while our programs use it.
DDLP shall help to avoid collisions between programs in the process of
recording to a CD or DVD drive and other programs which access that drive.
The protocol intends to provide advisory locking. So any good-willing program
has to take some extra precautions to participate.
If a program does not feel vulnerable to disturbance, then the precautions
impose much less effort than if the program feels the need for protection.
Two locking strategies are specified:
DDLP-A operates on device files only. It is very Linux specific.
DDLP-B adds proxy lock files, inspired by FHS /var/lock standard.
DDLP-A
This protocol relies on the hardly documented feature open(O_EXCL | O_RDWR)
with Linux device files and on POSIX compliant fcntl(F_SETLK).
Other than the original meaning of O_EXCL with creating regular files, the
effect on device files is mutual exclusion of access. I.e. if one
filedescriptor is open on that combination of major-minor device number, then
no other open(O_EXCL) will succeed. But open() without O_EXCL would succeed.
So this is advisory and exclusive locking.
With kernel 2.6 it seems to work on all device drivers which might get used
to access a CD/DVD drive.
The vulnerable programs shall not start their operation before they occupied a
wide collection of drive representations.
Non-vulnerable programs shall take care to detect the occupation of _one_ such
representation.
So for Friendly Programs
A program which does not feel vulnerable to disturbance is urged to access
CD/DVD drives by opening a file descriptor which will uphold the lock
as long as it does not get closed. There are two alternative ways to achieve
this.
Very reliable is
open( some_path , O_EXCL | ...)
But O_EXCL imposes restrictions and interferences:
- O_EXCL | O_RDONLY does not succeed with /dev/sg* !
- O_EXCL cannot provide shared locks for programs which only want to lock
against burn programs but not against their own peers.
- O_EXCL keeps from obtaining information by harmless activities.
- O_EXCL already has a meaning with devices which are mounted as filesystems.
This priority meaning is more liberal than the one needed for CD/DV recording
protection.
So it may be necessary to use a cautious open() without O_EXCL and to aquire
a POSIX lock via fcntl(). "Cautious" means to add O_NDELAY to the flags of
open(), because this is declared to avoid side effects within open().
With this gesture it is important to use the paths expected by our burn
programs: /dev/sr[0..255] /dev/scd[0..255] /dev/sg[0..255] /dev/hd[a..z]
because fcntl(F_SETLK) does not lock the device but only a device-inode.
std_path = one of the standard device files:
/dev/sr[0..255] /dev/scd[0..255] /dev/sg[0..255] /dev/hd[a..z]
or a symbolic link pointing to one of them.
open( std_path , ... | O_NDELAY)
fcntl(F_SETLK) and close() on failure
... eventually disable O_NDELAY by fcntl(F_SETFL) ...
There is a pitfall mentioned in man 2 fcntl :
"locks are automatically released [...] if it closes any file descriptor
referring to a file on which locks are held. This is bad [...]"
So you may have to re-lock after some temporary fd got closed.
Vulnerable Programs
For programs which do feel vulnerable, O_EXCL would suffice for the /dev/hd*
device file family and their driver. But USB and SATA recorders appear with
at least two different major-minor combinations simultaneously.
One as /dev/sr* alias /dev/scd*, the other as /dev/sg*.
The same is true for ide-scsi or recorders attached to SCSI controllers.
So, in order to lock any access to the recorder, one has to open(O_EXCL)
not only the device file that is intended for accessing the recorder but also
a device file of any other major-minor representation of the recorder.
This is done via the SCSI address parameter vector (Host,Channel,Id,Lun)
and a search on standard device file paths /dev/sr* /dev/scd* /dev/sg*.
In this text the alternative device representations are called "siblings".
For finding them, it is necessary to apply open() to many device files which
might be occupied by delicate operations. On the other hand it is very
important to occupy all reasonable representations of the drive.
So the reading of the (Host,Channel,Id,Lun) parameters demands an
open(O_RDONLY | O_NDELAY) _without_ fcntl() in order to find the outmost
number of representations among the standard device files. Only ioctls
SCSI_IOCTL_GET_IDLUN and SCSI_IOCTL_GET_BUS_NUMBER are applied.
Hopefully this gesture is unable to cause harmful side effects on kernel 2.6.
At least one file of each class sr, scd and sg should be found to regard
the occupation as satisfying. Thus corresponding sr-scd-sg triplets should have
matching ownerships and access permissions.
One will have to help the sysadmins to find those triplets.
A spicy detail is that sr and scd may be distinct device files for the same
major-minor combination. In this case fcntl() locks on both are needed
but O_EXCL can only be applied to one of them.
An open and free implementation ddlpa.[ch] is provided as
http://libburnia.pykix.org/browser/libburn/trunk/libburn/ddlpa.h?format=txt
http://libburnia.pykix.org/browser/libburn/trunk/libburn/ddlpa.c?format=txt
The current version of this text is
http://libburnia.pykix.org/browser/libburn/trunk/doc/ddlp.txt?format=txt
Put ddlpa.h and ddlpa.c into the same directory and compile as test program by
cc -g -Wall -DDDLPA_C_STANDALONE -o ddlpa ddlpa.c
Use it to occupy a drive's representations for a given number of seconds
./ddlpa /dev/sr0 300
It should do no harm to any of your running activities.
If it does: Please, please alert us.
Your own programs should not be able to circumvent the occupation if they
obey above rules for Friendly Programs.
Of course ./ddlpa should be unable to circumvent itself.
A successfull occupation looks like
DDLPA_DEBUG: ddlpa_std_by_rdev("/dev/scd0") = "/dev/sr0"
DDLPA_DEBUG: ddlpa_collect_siblings() found "/dev/sr0"
DDLPA_DEBUG: ddlpa_collect_siblings() found "/dev/scd0"
DDLPA_DEBUG: ddlpa_collect_siblings() found "/dev/sg0"
DDLPA_DEBUG: ddlpa_occupy() : '/dev/scd0'
DDLPA_DEBUG: ddlpa_occupy() O_EXCL : '/dev/sg0'
DDLPA_DEBUG: ddlpa_occupy() O_EXCL : '/dev/sr0'
---------------------------------------------- Lock gained
ddlpa: opened /dev/sr0
ddlpa: opened siblings: /dev/scd0 /dev/sg0
slept 1 seconds of 300
Now an attempt via device file alias /dev/NEC must fail:
DDLPA_DEBUG: ddlpa_std_by_rdev("/dev/NEC") = "/dev/sg0"
DDLPA_DEBUG: ddlpa_collect_siblings() found "/dev/sr0"
DDLPA_DEBUG: ddlpa_collect_siblings() found "/dev/scd0"
DDLPA_DEBUG: ddlpa_collect_siblings() found "/dev/sg0"
Cannot exclusively open '/dev/sg0'
Reason given : Failed to open O_RDWR | O_NDELAY | O_EXCL : '/dev/sr0'
Error condition : 16 'Device or resource busy'
With hdc, of course, things are trivial
DDLPA_DEBUG: ddlpa_std_by_rdev("/dev/hdc") = "/dev/hdc"
DDLPA_DEBUG: ddlpa_occupy() O_EXCL : '/dev/hdc'
---------------------------------------------- Lock gained
ddlpa: opened /dev/hdc
slept 1 seconds of 1
Ted Ts'o provided program open-cd-excl which allows to explore open(2) on
device files with combinations of read-write, O_EXCL, and fcntl().
(This does not mean that Ted endorsed our project yet. He helps exploring.)
Friendly in the sense of DDLP-A would be any run which uses at least one of
the options -e (i.e. O_EXCL) or -f (i.e. F_SETLK, applied to a file
descriptor which was obtained from a standard device file path).
The code is available under GPL at
http://libburnia.pykix.org/browser/libburn/trunk/test/open-cd-excl.c?format=txt
To be compiled by
cc -g -Wall -o open-cd-excl open-cd-excl.c
Options:
-e : open O_EXCL
-f : aquire lock by fcntl(F_SETLK) after sucessful open
-i : do not wait in case of success but exit 0 immediately
-r : open O_RDONLY , with -f use F_RDLCK
-w : open O_RDWR , with -f use F_WRLCK
plus the path of the devce file to open.
Friendly Programs would use gestures like:
./open-cd-excl -e -r /dev/sr0
./open-cd-excl -e -w /dev/sg1
./open-cd-excl -e -w /dev/black-drive
./open-cd-excl -f -r /dev/sg1
./open-cd-excl -e -f -w /dev/sr0
Ignorant programs would use and cause potential trouble by:
./open-cd-excl -r /dev/sr0
./open-cd-excl -w /dev/sg1
./open-cd-excl -f -w /dev/black-drive
where "/dev/black-drive" is _not_ a symbolic link to
any of /dev/sr* /dev/scd* /dev/sg* /dev/hd*, but has an own inode.
Prone to failure without further reason is:
./open-cd-excl -e -r /dev/sg1
----------------------------------------------------------------------------
DDLP-B
This protocol relies on proxy lock files in some filesystem directory. It can
be embedded into DDLP-A or it can be used be used standalone, outside DDLP-A.
DDLP-A shall be kept by DDLP-B from trying to access any device file which
might already be in use. There is a problematic gesture in DDLP-A when SCSI
address parameters are to be retrieved. For now this gesture seems to be
harmless. But one never knows.
Vice versa DDLP-B may get from DDLP-A the service to search for SCSI device
file siblings. So they are best as a couple.
But they are not perfect. Not even as couple. fcntl() locking is flawed.
There is a proxy file locking protocol described in FHS:
http://www.pathname.com/fhs/pub/fhs-2.3.html#VARLOCKLOCKFILES
But it has shortcommings (see below). Decisive obstacle for its usage are the
possibility for stale locks and the lack of shared locks.
DDLP-B rather defines a "path prefix" which is advised to be
/tmp/ddlpb-lock-
This prefix will get appended "device specific suffixes" and then form the path
of a "lockfile".
Not the existence of a lockfile but its occupation by an fcntl(F_SETLK) will
constitute a lock. Lockfiles may get prepared by the sysadmin in directories
where normal users are not allowed to create new files. Their rw-permissions
then act as additional access restriction to the device files.
The use of fcntl(F_SETLK) will prevent any stale locks after the process ended.
It will also allow to obtain shared locks as well as exclusive locks.
There are two classes of device specific suffixes:
- Device file path suffix. Absolute paths only. "/" gets replaced by "_-".
Eventual "_-" in path gets replaced by "_-_-". The leading group of "_-"
is always interpreted as a group of "/", though. E.g.:
/dev/sr0 <-> "_-dev_-sr0"
/mydevs/burner/nec <-> "_-mydevs_-burners_-nec"
/dev/rare_-name <-> "_-dev_-rare_-_-name"
///strange/dev/x <-> "_-_-_-strange_-dev_-x"
- st_rdev suffix. A hex representation of struct stat.st_rdev. Capital letters.
The number of characters is pare with at most one leading 0. I.e. bytewise
printf("%2.2X") beginning with the highest order byte that is not zero.
E.g. : "0B01", "2200", "01000000000004001"
If a lockfile does not exist and cannot be created then this shall not keep
a program from working on a device. But if a lockfile exists and if permissions
or locking state do not allow to obtain a lock of the appropirate type, then
this shall prevent any opening of device file in question resp. shall cause
immediate close(2) of an already opened device file.
The vulnerable programs shall not start their operation before they locked a
wide collection of drive representations.
Non-vulnerable programs shall take care to lock the suffix resulting from the
path they will be using and the suffix from the st_rdev from that path.
The latter is to be obtained by call stat(2).
Locks get upheld as long as their file descriptor is not closed or no other
incident as described in man 2 fcntl releases the lock.
So with shared locks there are no imandatory further activities after they
have been obtained.
In case of exclusive locks, the file has to have been opened for writing and
must be truncated to 0 bytes length immediately after obtaining the lock.
When releasing an exclusive lock it is a nice gesture to
already do this truncation.
Then a /var/lock/ compatible first line has to be written.
E.g. by: printf("%10u\n",(unsigned) getpid()) yielding " 1230\n".
Any further lines are optional. They shall have the form Name=Value and must
be printable cleartext. If such further lines exist, then the last one must
have the name "endmark".
Defined Names are:
hostid =hostname of the machine where the process number of line 1 is valid
start =start time of lock in seconds since 1970. E.g: 1177147634.592410
program =self chosen name of the program which obtained the lock
argv0 =argv[0] of that program
mainpath =device file path which will be used for operations by that program
path =device file path which lead to the lock
st_rdev =st_rdev suffix which is associated with path
scsi_hcil=eventual SCSI parameters Host,Channel,Id,Lun
scsi_bus =eventual SCSI parameter Bus
endmark =declares the info as complete.
Any undefined name or a line without "=" shall be handled as comment.
"=" in the value is allowed. Any line beginning with an "=" character is an
extension of the previous value.
If programs encounter an exclusive lock, they are invited to read the content
of the lockfile anyway. But they should be aware that the info might be in the
progress of emerging. There is a race condition possible in the short time
between obtaining the exclusive lock and erasing the file content.
If it is not crucial to obtain most accurate info then one may take the newline
of the first line as indicator of a valid process number and the "endmark"
name as indicator that the preceding lines are valid.
Very cautious readers should obtain the info twice with a decent waiting period
inbetween. Only if both results are identical they should be considered valid.
There is no implementation of DDLP-B yet.
----------------------------------------------------------------------------
What are the Stumble Stones ?
----------------------------------------------------------------------------
Any of the considered locking mechanisms has decisive shortcommings
which keeps it from being the solution to all known legitimate use cases.
The attempt has failed to compose a waterproof locking mechanism from means of
POSIX, FHS and from hardly documented Linux open(O_EXCL) on device files.
The resulting mechanisms would need about 1000 lines of code and still do
not close all gaps resp. cover the well motivated use cases.
This attempt you see above: DDLP-A and DDLP-B.
Summary of the reasons why the established locking mechanisms do not suffice:
None of the mechanisms can take care of the double device driver identity
sr versus sg. To deduce the one device file from the other involves the need
to open many other (possibly unrelated) device files with the risk to disturb
them.
This hard to solve problem is aggravated by the following facts.
Shortcommings of Linux specific open(O_EXCL) :
- O_EXCL | O_RDONLY does not succeed with /dev/sg*
- O_EXCL cannot provide shared locks for programs which only want to lock
against burn programs but not against their own peers.
- O_EXCL keeps from obtaining information by harmless activities.
- O_EXCL already has a meaning with devices which are mounted as filesystems.
This priority meaning is more liberal than the one needed for CD/DV recording
protection.
Shortcommings of POSIX fcntl(F_SETLK) :
- fcntl() demands an open file descriptor. open(2) might have side effects.
- fcntl() locks can be released inadvertedly by submodules which just open and
close the same file (inode ?) without refering to fcntl locks in any way.
See man 2 fcntl "This is bad:".
Stacking of software modules is a widely used design pattern. But fcntl()
cannot cope with that.
Shortcommings of FHS /var/lock/ :
- Stale locks are possible.
- It is necessary to create a file (using the _old_ meaning of O_EXCL flag ?)
but /var/lock/ might not be available early during system start and it often
has restrictive permission settings.
- There is no way to indicate a difference between exclusive and shared locks.
- The FHS prescription relies entirely on the basename of the device file path.

File diff suppressed because it is too large Load Diff

View File

@ -4,7 +4,7 @@ libdir=@libdir@
includedir=@includedir@
Name: libburn
Description: Disc reading/writing library
Description: Library to read/write optical discs
Version: @VERSION@
Requires:
Libs: -L${libdir} -lburn

View File

@ -1,15 +1,41 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* ts A71019 */
/* Standard measure should be: Threads are created detached.
According to the man pages they should then care for disposing themselves.
>>> ??? It is yet unclear why the threads vanish from the process list
even if joinable and even if never joined.
To be activated after release of libburn-0.4.0
*/
#define Libburn_create_detached_threadS 1
/* Alternative : Threads are created joinable.
Threads get detached in remove_worker() and thus should dispose themselves.
#define Libburn_detach_done_workeR 1
*/
#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 "back_hacks.h"
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
/*
#include <a ssert.h>
@ -17,7 +43,15 @@
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
#define SCAN_GOING() (workers && !workers->drive)
/* ts A80714 : introduced type codes for the worker list */
#define Burnworker_type_scaN 0
#define Burnworker_type_erasE 1
#define Burnworker_type_formaT 2
#define Burnworker_type_writE 3
#define Burnworker_type_fifO 4
#define SCAN_GOING() (workers != NULL && \
workers->w_type == Burnworker_type_scaN)
typedef void *(*WorkerFunc) (void *);
@ -35,6 +69,14 @@ struct erase_opts
int fast;
};
/* ts A61230 */
struct format_opts
{
struct burn_drive *drive;
off_t size;
int flag;
};
struct write_opts
{
struct burn_drive *drive;
@ -42,8 +84,18 @@ struct write_opts
struct burn_disc *disc;
};
struct fifo_opts
{
struct burn_source *source;
int flag;
};
struct w_list
{
/* ts A80714 */
int w_type; /* see above define Burnworker_type_* */
struct burn_drive *drive;
pthread_t thread;
@ -53,11 +105,14 @@ struct w_list
{
struct scan_opts scan;
struct erase_opts erase;
struct format_opts format;
struct write_opts write;
struct fifo_opts fifo;
} u;
};
static struct w_list *workers;
static struct w_list *workers = NULL;
static struct w_list *find_worker(struct burn_drive *d)
{
@ -69,12 +124,19 @@ static struct w_list *find_worker(struct burn_drive *d)
return NULL;
}
static void add_worker(struct burn_drive *d, WorkerFunc f, void *data)
static void add_worker(int w_type, struct burn_drive *d,
WorkerFunc f, void *data)
{
struct w_list *a;
struct w_list *tmp;
pthread_attr_t *attr_pt = NULL;
#ifdef Libburn_create_detached_threadS
pthread_attr_t attr;
#endif
a = malloc(sizeof(struct w_list));
a->w_type = w_type;
a->drive = d;
a->u = *(union w_list_data *)data;
@ -83,26 +145,65 @@ static void add_worker(struct burn_drive *d, WorkerFunc f, void *data)
tmp = workers;
workers = a;
if (d)
if (d != NULL)
d->busy = BURN_DRIVE_SPAWNING;
if (pthread_create(&a->thread, NULL, f, a)) {
#ifdef Libburn_create_detached_threadS
/* ts A71019 :
Trying to start the threads detached to get rid of the zombies
which do neither react on pthread_join() nor on pthread_detach().
*/
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
attr_pt= &attr;
/*
libdax_msgs_submit(libdax_messenger, -1, 0x00020158,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_LOW,
"add_worker(): Creating detached thread.", 0, 0);
*/
#endif
if (pthread_create(&a->thread, attr_pt, f, a)) {
free(a);
workers = tmp;
return;
}
}
static void remove_worker(pthread_t th)
{
struct w_list *a, *l = NULL;
#ifdef Libburn_detach_done_workeR
int ret;
char msg[80];
#endif
for (a = workers; a; l = a, a = a->next)
if (a->thread == th) {
if (l)
l->next = a->next;
else
workers = a->next;
#ifdef Libburn_detach_done_workeR
/* ts A71019 : burry dead puppy before forgetting it */
/* Alternative : threads get detached and thus should
dispose themselves.
*/
ret = pthread_detach(th);
/*
sprintf(msg,
"remove_workers(): pid= %lu pthread_detach(%lu)= %d",
(unsigned long) getpid(), (unsigned long) th, ret);
libdax_msgs_submit(libdax_messenger, -1, 0x00020158,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_LOW,
msg, 0, 0);
*/
#endif /* Libburn_detach_done_workeR */
free(a);
break;
}
@ -117,8 +218,13 @@ static void remove_worker(pthread_t th)
static void *scan_worker_func(struct w_list *w)
{
burn_drive_scan_sync(w->u.scan.drives, w->u.scan.n_drives);
w->u.scan.done = 1;
int ret;
ret = burn_drive_scan_sync(w->u.scan.drives, w->u.scan.n_drives, 1);
if (ret <= 0)
w->u.scan.done = -1;
else
w->u.scan.done = 1;
return NULL;
}
@ -152,12 +258,13 @@ drive_is_active:;
return -1;
}
if (!workers) {
if (workers == NULL) {
/* start it */
/* ts A61007 : test moved up from burn_drive_scan_sync()
was burn_wait_all() */
if (!burn_drives_are_clear())
/* ts A70907 : now demanding freed drives, not only released */
if (!burn_drives_are_clear(1))
goto drive_is_active;
*drives = NULL;
*n_drives = 0;
@ -165,7 +272,8 @@ drive_is_active:;
o.drives = drives;
o.n_drives = n_drives;
o.done = 0;
add_worker(NULL, (WorkerFunc) scan_worker_func, &o);
add_worker(Burnworker_type_scaN, NULL,
(WorkerFunc) scan_worker_func, &o);
} else if (workers->u.scan.done) {
/* its done */
ret = workers->u.scan.done;
@ -176,7 +284,7 @@ drive_is_active:;
if (workers != NULL) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020101,
LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
"After scan a drive operation is still going on",
"After scan a drive operation is still going on",
0, 0);
return -1;
}
@ -209,7 +317,7 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
"NULL pointer caught in burn_disc_erase", 0, 0);
return;
}
if ((SCAN_GOING()) || find_worker(drive)) {
if ((SCAN_GOING()) || find_worker(drive) != NULL) {
libdax_msgs_submit(libdax_messenger, drive->global_index,
0x00020102,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
@ -217,15 +325,195 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
0, 0);
return;
}
/* A70103 : will be set to 0 by burn_disc_erase_sync() */
drive->cancel = 1;
/* ts A70103 moved up from burn_disc_erase_sync() */
/* ts A60825 : allow on parole to blank appendable CDs */
/* ts A70131 : allow blanking of overwriteable DVD-RW (profile 0x13) */
/* ts A70216 : allow blanking of CD-RW or DVD-RW in any regular state
and of any kind of full media */
/* ts A70909 : the willingness to burn any BURN_DISC_FULL media is
inappropriate. One would rather need a -force option
Note: keep this in sync with mmc_read_disc_info() */
if ((drive->current_profile != 0x0a &&
drive->current_profile != 0x13 &&
drive->current_profile != 0x14 &&
drive->status != BURN_DISC_FULL)
||
(drive->status != BURN_DISC_FULL &&
drive->status != BURN_DISC_APPENDABLE &&
drive->status != BURN_DISC_BLANK)
||
(drive->drive_role != 1)
) {
libdax_msgs_submit(libdax_messenger, drive->global_index,
0x00020130,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Drive and media state unsuitable for blanking",
0, 0);
return;
}
o.drive = drive;
o.fast = fast;
add_worker(drive, (WorkerFunc) erase_worker_func, &o);
add_worker(Burnworker_type_erasE, drive,
(WorkerFunc) erase_worker_func, &o);
}
/* ts A61230 */
static void *format_worker_func(struct w_list *w)
{
burn_disc_format_sync(w->u.format.drive, w->u.format.size,
w->u.format.flag);
remove_worker(pthread_self());
return NULL;
}
/* ts A61230 */
void burn_disc_format(struct burn_drive *drive, off_t size, int flag)
{
struct format_opts o;
int ok = 0, ret;
char msg[160];
if ((SCAN_GOING()) || find_worker(drive) != NULL) {
libdax_msgs_submit(libdax_messenger, drive->global_index,
0x00020102,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"A drive operation is still going on (want to format)",
0, 0);
return;
}
if (drive->drive_role != 1) {
libdax_msgs_submit(libdax_messenger, drive->global_index,
0x00020146,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Drive is a virtual placeholder", 0, 0);
drive->cancel = 1;
return;
}
if (flag & 128) /* application prescribed format type */
flag |= 16; /* enforce re-format */
if (drive->current_profile == 0x14)
ok = 1; /* DVD-RW sequential */
else if (drive->current_profile == 0x13 && (flag & 16))
ok = 1; /* DVD-RW Restricted Overwrite with force bit */
else if (drive->current_profile == 0x1a) {
ok = 1; /* DVD+RW */
size = 0;
flag &= ~(2|8); /* no insisting in size 0, no expansion */
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) {
sprintf(msg,"Will not format media type %4.4Xh",
drive->current_profile);
libdax_msgs_submit(libdax_messenger, drive->global_index,
0x00020129,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
drive->cancel = 1;
return;
}
o.drive = drive;
o.size = size;
o.flag = flag;
add_worker(Burnworker_type_formaT, drive,
(WorkerFunc) format_worker_func, &o);
}
static void *write_disc_worker_func(struct w_list *w)
{
struct burn_drive *d = w->u.write.drive;
d->thread_pid = getpid();
d->thread_pid_valid= 1;
burn_disc_write_sync(w->u.write.opts, w->u.write.disc);
d->thread_pid_valid= 0;
d->thread_pid = 0;
/* the options are refcounted, free out ref count which we added below
*/
@ -238,11 +526,12 @@ static void *write_disc_worker_func(struct w_list *w)
void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
{
struct write_opts o;
char reasons[BURN_REASONS_LEN+80];
/* ts A61006 */
/* a ssert(!SCAN_GOING()); */
/* a ssert(!find_worker(opts->drive)); */
if ((SCAN_GOING()) || find_worker(opts->drive)) {
if ((SCAN_GOING()) || find_worker(opts->drive) != NULL) {
libdax_msgs_submit(libdax_messenger, opts->drive->global_index,
0x00020102,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
@ -250,17 +539,45 @@ void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
0, 0);
return;
}
/* For the next lines any return indicates failure */
opts->drive->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,
0x00020146,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Drive is a virtual placeholder (null-drive)", 0, 0);
return;
}
/* ts A61007 : obsolete Assert in spc_select_write_params() */
if (!opts->drive->mdata->valid) {
if (opts->drive->drive_role == 1 && !opts->drive->mdata->valid) {
libdax_msgs_submit(libdax_messenger,
opts->drive->global_index, 0x00020113,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Drive capabilities not inquired yet", 0, 0);
return;
}
/* ts A61009 : obsolete Assert in sector_headers() */
if (! burn_disc_write_is_ok(opts, disc)) /* issues own msgs */
/* ts A70219 : intended to replace all further tests here and many
tests in burn_*_write_sync()
*/
strcpy(reasons, "Write job parameters are unsuitable:\n");
if (burn_precheck_write(opts, disc, reasons + strlen(reasons), 1)
<= 0) {
libdax_msgs_submit(libdax_messenger,
opts->drive->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 */
o.drive = opts->drive;
o.opts = opts;
@ -268,9 +585,72 @@ void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
opts->refcount++;
add_worker(opts->drive, (WorkerFunc) write_disc_worker_func, &o);
add_worker(Burnworker_type_writE, opts->drive,
(WorkerFunc) write_disc_worker_func, &o);
}
static void *fifo_worker_func(struct w_list *w)
{
int old;
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());
return NULL;
}
int burn_fifo_start(struct burn_source *source, int flag)
{
struct fifo_opts o;
struct burn_source_fifo *fs = source->data;
fs->is_started = -1;
/* create and set up ring buffer */;
fs->buf = calloc(fs->chunksize, fs->chunks);
if (fs->buf == NULL) {
/* >>> could not start ring buffer */;
return -1;
}
o.source = source;
o.flag = 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 */
void burn_async_join_all(void)
{
void *ret;
@ -278,3 +658,7 @@ void burn_async_join_all(void)
while (workers)
pthread_join(workers->thread, &ret);
}
#endif /* Libburn_has_burn_async_join_alL */

View File

@ -5,4 +5,14 @@
void burn_async_join_all(void);
struct burn_write_opts;
/* ts A70930 */
/* 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

@ -23,31 +23,27 @@ typedef void (*sighandler_t)(int);
#include "cleanup.h"
#ifdef __FreeBSD__
#ifndef Cleanup_has_no_libburn_os_H
#include "../libburn/os.h"
/* see os.h for name of particular os-*.h where this is defined */
static int signal_list[]= { BURN_OS_SIGNAL_MACRO_LIST , -1};
static char *signal_name_list[]= { BURN_OS_SIGNAL_NAME_LIST , "@"};
static int signal_list_count= BURN_OS_SIGNAL_COUNT;
static int non_signal_list[]= { BURN_OS_NON_SIGNAL_MACRO_LIST, -1};
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 */
/* Signals to be caught */
static int signal_list[]= {
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT,
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM,
SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN,
SIGTTOU,
SIGBUS, SIGPROF, SIGSYS, SIGTRAP,
SIGVTALRM, SIGXCPU, SIGXFSZ, -1
};
static char *signal_name_list[]= {
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT",
"SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM",
"SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN",
"SIGTTOU",
"SIGBUS", "SIGPROF", "SIGSYS", "SIGTRAP",
"SIGVTALRM", "SIGXCPU", "SIGXFSZ", "@"
};
static int signal_list_count= 23;
#else /* __FreeBSD__ */
/* Signals to be caught */
static int signal_list[]= {
static int signal_list[]= {
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT,
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM,
SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN,
@ -55,7 +51,7 @@ static int signal_list[]= {
SIGBUS, SIGPOLL, SIGPROF, SIGSYS, SIGTRAP,
SIGVTALRM, SIGXCPU, SIGXFSZ, -1
};
static char *signal_name_list[]= {
static char *signal_name_list[]= {
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT",
"SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM",
"SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN",
@ -65,18 +61,21 @@ static char *signal_name_list[]= {
};
static int signal_list_count= 24;
#endif /* ! __FreeBSD__ */
/* Signals not to be caught */
static int non_signal_list[]= {
SIGKILL, SIGCHLD, SIGSTOP, SIGURG, -1
};
static int non_signal_list_count= 4;
SIGKILL, SIGCHLD, SIGSTOP, SIGURG, SIGWINCH, -1
};
static int non_signal_list_count= 5;
#endif /* Cleanup_has_no_libburn_os_H */
/* run time dynamic part */
static char cleanup_msg[4096]= {""};
static int cleanup_exiting= 0;
static int cleanup_has_reported= -1234567890;
static void *cleanup_app_handle= NULL;
static Cleanup_app_handler_T cleanup_app_handler= NULL;
@ -87,8 +86,10 @@ static int Cleanup_handler_exit(int exit_value, int signum, int flag)
{
int ret;
if(cleanup_msg[0]!=0)
if(cleanup_msg[0]!=0 && cleanup_has_reported!=signum) {
fprintf(stderr,"\n%s\n",cleanup_msg);
cleanup_has_reported= signum;
}
if(cleanup_perform_app_handler_first)
if(cleanup_app_handler!=NULL) {
ret= (*cleanup_app_handler)(cleanup_app_handle,signum,0);

614
libburn/ddlpa.c Normal file
View File

@ -0,0 +1,614 @@
/* ddlpa
Implementation of Delicate Device Locking Protocol level A.
Copyright (C) 2007 Thomas Schmitt <scdbackup@gmx.net>
Provided under any of the following licenses: GPL, LGPL, BSD. Choose one.
Compile as test program:
cc -g -Wall \
-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1 -D_LARGEFILE64_SOURCE \
-DDDLPA_C_STANDALONE -o ddlpa ddlpa.c
The system macros enable 64-bit off_t and open(2) flag O_LARGEFILE, which
are not absolutely necessary but explicitely take into respect that
our devices can offer more than 2 GB of addressable data.
Run test program:
./ddlpa /dev/sr0 15
./ddlpa 0,0,0 15
*/
#include <stdio.h>
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <scsi/scsi.h>
/* All callers of ddlpa must do this */
#include "ddlpa.h"
/* 1 = Enable progress message on stderr, 0 = normal silent operation */
static int ddlpa_debug_mode = 1;
/* #define _GNU_SOURCE or _LARGEFILE64_SOURCE to get real O_LARGEFILE */
#ifndef O_LARGEFILE
#define O_LARGEFILE 0
#endif
/* ----------------------- private -------------------- */
static int ddlpa_new(struct ddlpa_lock **lck, int o_flags, int ddlpa_flags)
{
int i;
struct ddlpa_lock *o;
o = *lck = (struct ddlpa_lock *) malloc(sizeof(struct ddlpa_lock));
if (o == NULL)
return ENOMEM;
for (i = 0; i < sizeof(struct ddlpa_lock); i++)
((char *) o)[i] = 0;
o->path = NULL;
o->fd = -1;
for (i = 0; i < DDLPA_MAX_SIBLINGS; i++)
o->sibling_fds[i] = -1;
o->errmsg = NULL;
o->o_flags = o_flags;
o->ddlpa_flags = ddlpa_flags;
return 0;
}
static int ddlpa_enumerate(struct ddlpa_lock *o, int *idx,
char path[DDLPA_MAX_STD_LEN + 1])
{
if (*idx < 0)
*idx = 0;
if (*idx < 26)
sprintf(path, "/dev/hd%c", 'a' + *idx);
else if (*idx < 256 + 26)
sprintf(path, "/dev/sr%d", *idx - 26);
else if (*idx < 2 * 256 + 26)
sprintf(path, "/dev/scd%d", *idx - 256 - 26);
else if (*idx < 3 * 256 + 26)
sprintf(path, "/dev/sg%d", *idx - 2 * 256 - 26);
else
return 1;
(*idx)++;
return 0;
}
static int ddlpa_std_by_rdev(struct ddlpa_lock *o)
{
int idx = 0;
char try_path[DDLPA_MAX_STD_LEN+1];
struct stat path_stbuf, try_stbuf;
if (!o->path_is_valid)
return EFAULT;
if (stat(o->path, &path_stbuf) == -1)
return errno;
while (ddlpa_enumerate(o, &idx, try_path) == 0) {
if (stat(try_path, &try_stbuf) == -1)
continue;
if (path_stbuf.st_rdev != try_stbuf.st_rdev)
continue;
strcpy(o->std_path, try_path);
if (ddlpa_debug_mode)
fprintf(stderr,
"DDLPA_DEBUG: ddlpa_std_by_rdev(\"%s\") = \"%s\"\n",
o->path, o->std_path);
return 0;
}
return ENOENT;
}
/* Caution : these tests are valid only with standard paths */
static int ddlpa_is_scsi(struct ddlpa_lock *o, char *path)
{
return (strncmp(path, "/dev/s", 6) == 0);
}
static int ddlpa_is_sg(struct ddlpa_lock *o, char *path)
{
return (strncmp(path, "/dev/sg", 7) == 0);
}
static int ddlpa_is_sr(struct ddlpa_lock *o, char *path)
{
return (strncmp(path, "/dev/sr", 7) == 0);
}
static int ddlpa_is_scd(struct ddlpa_lock *o, char *path)
{
return (strncmp(path, "/dev/scd", 8) == 0);
}
static int ddlpa_fcntl_lock(struct ddlpa_lock *o, int fd, int l_type)
{
struct flock lockthing;
int ret;
memset(&lockthing, 0, sizeof(lockthing));
lockthing.l_type = l_type;
lockthing.l_whence = SEEK_SET;
lockthing.l_start = 0;
lockthing.l_len = 0;
ret = fcntl(fd, F_SETLK, &lockthing);
if (ret == -1)
return EBUSY;
return 0;
}
static int ddlpa_occupy(struct ddlpa_lock *o, char *path, int *fd,
int no_o_excl)
{
int ret, o_flags, o_rw, l_type;
char *o_rwtext;
o_flags = o->o_flags | O_NDELAY;
if(!no_o_excl)
o_flags |= O_EXCL;
o_rw = (o_flags) & (O_RDONLY | O_WRONLY | O_RDWR);
o_rwtext = (o_rw == O_RDONLY ? "O_RDONLY" :
(o_rw == O_WRONLY ? "O_WRONLY" :
(o_rw == O_RDWR ? "O_RDWR " : "O_?rw-mode?")));
*fd = open(path, o_flags);
if (*fd == -1) {
o->errmsg = malloc(strlen(path)+160);
if (o->errmsg)
sprintf(o->errmsg,
"Failed to open %s | O_NDELAY %s: '%s'",
o_rwtext,
(o_flags & O_EXCL ? "| O_EXCL " : ""), path);
return (errno ? errno : EBUSY);
}
if (o_rw == O_RDWR || o_rw == O_WRONLY)
l_type = F_WRLCK;
else
l_type = F_RDLCK;
ret = ddlpa_fcntl_lock(o, *fd, l_type);
if (ret) {
o->errmsg = malloc(strlen(path)+160);
if (o->errmsg)
sprintf(o->errmsg,
"Failed to lock fcntl(F_WRLCK) : '%s'",path);
close(*fd);
*fd = -1;
return ret;
}
if (ddlpa_debug_mode)
fprintf(stderr, "DDLPA_DEBUG: ddlpa_occupy() %s %s: '%s'\n",
o_rwtext,
(no_o_excl ? " " : "O_EXCL "), path);
return 0;
}
static int ddlpa_obtain_scsi_adr(struct ddlpa_lock *o, char *path,
int *bus, int *host, int *channel, int *id, int *lun)
{
int fd, ret, open_mode = O_RDONLY | O_NDELAY;
struct my_scsi_idlun {
int x;
int host_unique_id;
};
struct my_scsi_idlun idlun;
fd = open(path, open_mode);
if (fd == -1)
return (errno ? errno : EBUSY);
if (ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, bus) == -1)
*bus = -1;
ret = ioctl(fd, SCSI_IOCTL_GET_IDLUN, &idlun);
close(fd);
if (ret == -1)
return (errno ? errno : EIO);
*host = (idlun.x >> 24) & 255;
*channel = (idlun.x >> 16) & 255;
*id = (idlun.x) & 255;
*lun = (idlun.x >> 8 ) & 255;
return 0;
}
static int ddlpa_collect_siblings(struct ddlpa_lock *o)
{
int idx = 0, ret, have_sg = 0, have_sr = 0, have_scd = 0;
dev_t path_dev;
ino_t path_inode;
struct stat stbuf;
char *path, try_path[DDLPA_MAX_STD_LEN+1];
int t_bus, t_host, t_channel, t_id, t_lun;
if (o->ddlpa_flags & DDLPA_OPEN_GIVEN_PATH)
path = o->path;
else
path = o->std_path;
if (path[0] == 0 || o->num_siblings != 0)
return EFAULT;
if (!ddlpa_is_scsi(o, o->std_path))
return EFAULT;
if (stat(path, &stbuf) == -1)
return errno;
path_inode = stbuf.st_ino;
path_dev = stbuf.st_dev;
o->rdev = stbuf.st_rdev;
o->dev = stbuf.st_dev;
o->ino = stbuf.st_ino;
ret = ddlpa_obtain_scsi_adr(o, path,
&(o->bus), &(o->host), &(o->channel),
&(o->id), &(o->lun));
if (ret) {
o->errmsg = strdup(
"Cannot obtain SCSI parameters host,channel,id,lun");
return ret;
}
o->hcilb_is_valid = 1;
while (ddlpa_enumerate(o, &idx, try_path) == 0) {
if (!ddlpa_is_scsi(o, try_path))
continue;
if (stat(try_path, &stbuf) == -1)
continue;
ret = ddlpa_obtain_scsi_adr(o, try_path,
&t_bus, &t_host, &t_channel, &t_id, &t_lun);
if (ret) {
/* >>> interpret error, memorize busy, no permission */
continue;
}
if (t_host != o->host || t_channel != o->channel ||
t_id != o->id || t_lun != o->lun)
continue;
if (o->num_siblings >= DDLPA_MAX_SIBLINGS) {
o->errmsg =
strdup("Too many matching device files found");
return ERANGE;
}
if (ddlpa_is_sg(o, try_path))
have_sg = 1;
else if (ddlpa_is_sr(o, try_path))
have_sr = 1;
else if (ddlpa_is_scd(o, try_path))
have_scd = 1;
strcpy(o->sibling_paths[o->num_siblings], try_path);
o->sibling_rdevs[o->num_siblings] = stbuf.st_rdev;
o->sibling_devs[o->num_siblings] = stbuf.st_dev;
o->sibling_inodes[o->num_siblings] = stbuf.st_ino;
if (ddlpa_debug_mode)
fprintf(stderr,
"DDLPA_DEBUG: ddlpa_collect_siblings() found \"%s\"\n",
try_path);
(o->num_siblings)++;
}
if (have_sg && have_sr && have_scd)
return 0;
if (o->ddlpa_flags & DDLPA_ALLOW_MISSING_SGRCD)
return 0;
o->errmsg = strdup("Did not find enough siblings");
/* >>> add more info about busy and forbidden paths */
return EBUSY;
}
static int ddlpa_std_by_btl(struct ddlpa_lock *o)
{
int idx = 0, ret;
char try_path[DDLPA_MAX_STD_LEN+1];
int t_bus, t_host, t_channel, t_id, t_lun;
if (!o->inbtl_is_valid)
return EFAULT;
while (ddlpa_enumerate(o, &idx, try_path) == 0) {
if (!ddlpa_is_sr(o, try_path))
continue;
ret = ddlpa_obtain_scsi_adr(o, try_path,
&t_bus, &t_host, &t_channel, &t_id, &t_lun);
if (ret) {
/* >>> interpret error, memorize busy, no permission */
continue;
}
if (t_bus != o->in_bus || t_id != o->in_target ||
t_lun != o->in_lun)
continue;
strcpy(o->std_path, try_path);
if (ddlpa_debug_mode)
fprintf(stderr,
"DDLPA_DEBUG: ddlpa_std_by_btl(%d,%d,%d) = \"%s\"\n",
t_bus, t_id, t_lun, o->std_path);
return 0;
}
/* >>> add more info about busy and forbidden paths */
return ENOENT;
}
static int ddlpa_open_all(struct ddlpa_lock *o)
{
int i, j, ret, no_o_excl;
if (ddlpa_is_scsi(o, o->std_path)) {
ret = ddlpa_collect_siblings(o);
if (ret)
return ret;
for (i = 0; i < o->num_siblings; i++) {
/* Watch out for the main personality of the drive. */
/* No need to occupy identical path or softlink path */
if (o->sibling_devs[i] == o->dev &&
o->sibling_inodes[i] == o->ino)
continue;
/* There may be the same rdev but different inode. */
no_o_excl = (o->sibling_rdevs[i] == o->rdev);
/* Look for multiply registered device drivers with
distinct inodes. */
for (j = 0; j < i; j++) {
if (o->sibling_devs[j] == o->sibling_devs[i] &&
o->sibling_inodes[j] == o->sibling_inodes[i])
break;
if (o->sibling_rdevs[j] == o->sibling_rdevs[i])
no_o_excl = 1;
}
if (j < i)
continue; /* inode is already occupied */
ret = ddlpa_occupy(o, o->sibling_paths[i],
&(o->sibling_fds[i]), no_o_excl);
if (ret)
return ret;
}
}
if (o->ddlpa_flags & DDLPA_OPEN_GIVEN_PATH)
ret = ddlpa_occupy(o, o->path, &(o->fd), 0);
else
ret = ddlpa_occupy(o, o->std_path, &(o->fd), 0);
if (ret)
return ret;
/* >>> use fcntl() to adjust O_NONBLOCK */;
return 0;
}
/* ----------------------- public -------------------- */
int ddlpa_destroy(struct ddlpa_lock **lockbundle)
{
struct ddlpa_lock *o;
int i;
o= *lockbundle;
if (o == NULL)
return 0;
for (i = 0; i < o->num_siblings; i++)
if (o->sibling_fds[i] != -1)
close(o->sibling_fds[i]);
if(o->fd != -1)
close(o->fd);
if (o->path != NULL)
free(o->path);
if (o->errmsg != NULL)
free(o->errmsg);
free((char *) o);
*lockbundle = NULL;
return 0;
}
int ddlpa_lock_path(char *path, int o_flags, int ddlpa_flags,
struct ddlpa_lock **lockbundle, char **errmsg)
{
struct ddlpa_lock *o;
int ret;
*errmsg = NULL;
if (ddlpa_new(&o, o_flags, ddlpa_flags))
return ENOMEM;
*lockbundle = o;
o->path = strdup(path);
if (o->path == NULL)
return ENOMEM;
o->path_is_valid = 1;
ret = ddlpa_std_by_rdev(o);
if (ret) {
*errmsg = strdup(
"Cannot find equivalent of given path among standard paths");
return ret;
}
ret = ddlpa_open_all(o);
if (ret) {
*errmsg = o->errmsg;
o->errmsg = NULL;
ddlpa_destroy(&o);
}
return ret;
}
int ddlpa_lock_btl(int bus, int target, int lun,
int o_flags, int ddlpa_flags,
struct ddlpa_lock **lockbundle, char **errmsg)
{
struct ddlpa_lock *o;
int ret;
*errmsg = NULL;
ddlpa_flags &= ~DDLPA_OPEN_GIVEN_PATH;
if (ddlpa_new(&o, o_flags, ddlpa_flags))
return ENOMEM;
*lockbundle = o;
o->in_bus = bus;
o->in_target = target;
o->in_lun = lun;
o->inbtl_is_valid = 1;
ret = ddlpa_std_by_btl(o);
if (ret) {
*errmsg = strdup(
"Cannot find /dev/sr* with given Bus,Target,Lun");
return ret;
}
ret = ddlpa_open_all(o);
if (ret) {
*errmsg = o->errmsg;
o->errmsg = NULL;
ddlpa_destroy(&o);
return ret;
}
return 0;
}
#ifdef DDLPA_C_STANDALONE
/* ----------------------------- Test / Demo -------------------------- */
int main(int argc, char **argv)
{
struct ddlpa_lock *lck = NULL;
char *errmsg = NULL, *opened_path = NULL, *my_path = NULL;
int i, ret, fd = -1, duration = -1, bus = -1, target = -1, lun = -1;
if (argc < 3) {
usage:;
fprintf(stderr, "usage: %s device_path duration\n", argv[0]);
exit(1);
}
my_path = argv[1];
sscanf(argv[2], "%d", &duration);
if (duration < 0)
goto usage;
/* For our purpose, only O_RDWR is a suitable access mode.
But in order to allow experiments, o_flags are freely adjustable.
Warning: Do _not_ set an own O_EXCL flag with the following calls !
(This freedom to fail may get removed in a final version.)
*/
if (my_path[0] != '/' && my_path[0] != '.' &&
strchr(my_path, ',') != NULL) {
/*
cdrecord style dev=Bus,Target,Lun
*/
sscanf(my_path, "%d,%d,%d", &bus, &target, &lun);
ret = ddlpa_lock_btl(bus, target, lun, O_RDWR | O_LARGEFILE,
0, &lck, &errmsg);
} else {
/*
This substitutes for:
fd = open(my_path, O_RDWR | O_EXCL | O_LARGEFILE);
*/
ret = ddlpa_lock_path(my_path, O_RDWR | O_LARGEFILE,
0, &lck, &errmsg);
}
if (ret) {
fprintf(stderr, "Cannot exclusively open '%s'\n", my_path);
if (errmsg != NULL)
fprintf(stderr, "Reason given : %s\n",
errmsg);
free(errmsg);
fprintf(stderr, "Error condition : %d '%s'\n",
ret, strerror(ret));
exit(2);
}
fd = lck->fd;
printf("---------------------------------------------- Lock gained\n");
/* Use fd for the usual operations on the device depicted by my_path.
*/
/* This prints an overview of the impact of the lock */
if (lck->ddlpa_flags & DDLPA_OPEN_GIVEN_PATH)
opened_path = lck->path;
else
opened_path = lck->std_path;
printf("ddlpa: opened %s", opened_path);
if (strcmp(opened_path, lck->std_path) != 0)
printf(" (an alias of '%s')", lck->std_path);
printf("\n");
if (lck->num_siblings > 0) {
printf("ddlpa: opened siblings:");
for (i = 0; i < lck->num_siblings; i++)
if (lck->sibling_fds[i] != -1)
printf(" %s", lck->sibling_paths[i]);
printf("\n");
}
/* This example waits a while. So other lock candidates can collide. */
for (i = 0; i < duration; i++) {
sleep(1);
fprintf(stderr, "\rslept %d seconds of %d", i + 1, duration);
}
fprintf(stderr, "\n");
/* When finally done with the drive, this substitutes for:
close(fd);
*/
if (ddlpa_destroy(&lck)) {
/* Well, man 2 close says it can fail. */
exit(3);
}
exit(0);
}
#endif /* DDLPA_C_STANDALONE */

107
libburn/ddlpa.h Normal file
View File

@ -0,0 +1,107 @@
/* ddlpa
Implementation of Delicate Device Locking Protocol level A.
Copyright (C) 2007 Thomas Schmitt <scdbackup@gmx.net>
Provided under any of the following licenses: GPL, LGPL, BSD. Choose one.
See ../doc/ddlp.txt for a description of the protocol.
*/
#ifndef DDLPA_H_INCLUDED
#define DDLPA_H_INCLUDED 1
/* An upper limit for the length of standard paths and sibling paths */
#define DDLPA_MAX_STD_LEN 15
/* An upper limit for the number of siblings */
#define DDLPA_MAX_SIBLINGS 5
struct ddlpa_lock {
/* Recorded input parameters of locking call */
char *path;
int path_is_valid;
int in_bus, in_target, in_lun;
int inbtl_is_valid;
int ddlpa_flags;
int o_flags;
/* Result of locking call */
char std_path[DDLPA_MAX_STD_LEN + 1];
int fd;
dev_t rdev;
dev_t dev;
ino_t ino;
int host, channel, id, lun, bus;
int hcilb_is_valid;
int num_siblings;
char sibling_paths[DDLPA_MAX_SIBLINGS][DDLPA_MAX_STD_LEN + 1];
int sibling_fds[DDLPA_MAX_SIBLINGS];
dev_t sibling_rdevs[DDLPA_MAX_SIBLINGS];
dev_t sibling_devs[DDLPA_MAX_SIBLINGS];
ino_t sibling_inodes[DDLPA_MAX_SIBLINGS];
/* Is NULL if all goes well. Else it may contain a text message. */
char *errmsg;
};
/** Lock a recorder by naming a device file path. Allocate a new container.
@param path Gives the file system path of the recorder
as known to the calling program.
@param o_flags flags for open(2). Do not use O_EXCL here because this
is done automatically whenever appropriate.
Advised is O_RDWR | O_LARGEFILE, eventually | O_NDELAY.
@param ddlpa_flags 0 = default behavior: the standard path will be opened
and treated by fcntl(F_SETLK)
DDLPA_OPEN_GIVEN_PATH causes the input parameter "path"
to be used with open(2) and fcntl(2).
DDLPA_ALLOW_MISSING_SGRCD allows to grant a lock
although not all three, a sg, a sr and a scd device
file have been found during sibling search. Normally
this is counted as failure due to EBUSY.
@param lockbundle gets allocated and then represents the locking state
@param errmsg if *errmsg is not NULL after the call, it contains an
error message. Then to be released by free(3).
It is NULL in case of success or lack of memory.
@return 0=success , else an errno compatible error number
*/
int ddlpa_lock_path(char *path, int o_flags, int ddlpa_flags,
struct ddlpa_lock **lockbundle, char **errmsg);
/** Lock a recorder by naming a Bus,Target,Lun number triple.
Allocate a new container.
@param bus parameter to match ioctl(SCSI_IOCTL_GET_BUS_NUMBER)
@param target parameter to match ioctl(SCSI_IOCTL_GET_IDLUN) &0xff
@param lun parameter to match ioctl(SCSI_IOCTL_GET_IDLUN) &0xff00
@param o_flags see ddlpa_lock_path().
@param ddlpa_flags see ddlpa_lock_path(). Flag DDLPA_OPEN_GIVEN_PATH
will be ignored.
@param lockbundle see ddlpa_lock_path().
@param errmsg see ddlpa_lock_path().
@return 0=success , else an errno compatible error number
*/
int ddlpa_lock_btl(int bus, int target, int lun,
int o_flags, int ddlpa_flags,
struct ddlpa_lock **lockbundle, char **errmsg);
/** Release the lock by closing all filedescriptors and freeing memory.
@param lockbundle the lock which is to be released.
*lockbundle will be set to NULL by this call.
@return 0=success , 1=failure
*/
int ddlpa_destroy(struct ddlpa_lock **lockbundle);
/** Definitions of macros used in above functions */
#define DDLPA_OPEN_GIVEN_PATH 1
#define DDLPA_ALLOW_MISSING_SGRCD 2
#endif /* DDLPA_H_INCLUDED */

File diff suppressed because it is too large Load Diff

View File

@ -10,6 +10,8 @@
struct burn_drive;
struct command;
struct mempage;
struct scsi_mode_data;
struct burn_speed_descriptor;
#define LEAD_IN 1
#define GAP 2
@ -41,7 +43,8 @@ unsigned int burn_drive_count(void);
/* ts A61007 */
/* void burn_wait_all(void); */
int burn_drives_are_clear(void);
/* @param flag bit0= demand freed drives (else released drives) */
int burn_drives_are_clear(int flag);
int burn_sector_length_write(struct burn_drive *d);
int burn_track_control(struct burn_drive *d, int);
@ -50,8 +53,10 @@ void burn_write_empty_subcode(int fd);
void burn_drive_free(struct burn_drive *d);
void burn_drive_free_all(void);
/* @param flag bit0= reset global drive list */
int burn_drive_scan_sync(struct burn_drive_info *drives[],
unsigned int *n_drives);
unsigned int *n_drives, int flag);
void burn_disc_erase_sync(struct burn_drive *d, int fast);
int burn_drive_get_block_types(struct burn_drive *d,
enum burn_write_types write_type);
@ -69,5 +74,65 @@ int burn_setup_drive(struct burn_drive *d, char *fname);
*/
struct burn_drive *burn_drive_finish_enum(struct burn_drive *d);
/* ts A61125 : media status aspects of burn_drive_grab() */
int burn_drive_inquire_media(struct burn_drive *d);
/* ts A61125 : model aspects of burn_drive_release */
int burn_drive_mark_unready(struct burn_drive *d);
/* ts A61226 */
int burn_speed_descriptor_new(struct burn_speed_descriptor **s,
struct burn_speed_descriptor *prev,
struct burn_speed_descriptor *next, int flag);
/* ts A61226 */
/* @param flag bit0= destroy whole next-chain of descriptors */
int burn_speed_descriptor_destroy(struct burn_speed_descriptor **s, int flag);
/* ts A61226 : free dynamically allocated sub data of struct scsi_mode_data */
int burn_mdata_free_subs(struct scsi_mode_data *m);
/* ts A61230 */
void burn_disc_format_sync(struct burn_drive *d, off_t size, int flag);
/* ts A70207 : evaluate write mode related peculiarities of a disc */
struct burn_disc_mode_demands {
int multi_session;
int multi_track;
int unknown_track_size; /* 0=known, 1=unknown, 2=unknown+defaulted */
int mixed_mode;
int audio;
int exotic_track;
int block_types;
int will_append; /* because of media state or multi session disc */
};
int burn_disc_get_write_mode_demands(struct burn_disc *disc,
struct burn_write_opts *opts,
struct burn_disc_mode_demands *result, int flag);
/* ts A70924 : convert a special stdio address into fd number.
@return >0 is a valid fd , -1 indicates unsuitable address string.
*/
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 A51221 - A80731 : Whitelist inquiry functions */
int burn_drive_is_banned(char *device_address);
int burn_drive_whitelist_count(void);
char *burn_drive_whitelist_item(int idx, int flag);
/* ts A80801 */
int burn_drive_is_listed(char *path, struct burn_drive **found, int flag);
#endif /* __DRIVE */

View File

@ -2,12 +2,23 @@
#include <stdlib.h>
#include <sys/types.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/stat.h>
#include <unistd.h>
#include <fcntl.h>
#include <time.h>
#include <pthread.h>
#include "source.h"
#include "libburn.h"
#include "file.h"
#include "async.h"
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
/* main channel data can be padded on read, but 0 padding the subs will make
an unreadable disc */
@ -42,7 +53,7 @@ static int file_read(struct burn_source *source,
unsigned char *buffer,
int size)
{
struct burn_source_fd *fs = source->data;
struct burn_source_file *fs = source->data;
return read_full_buffer(fs->datafd, buffer, size);
}
@ -71,26 +82,36 @@ static off_t file_size(struct burn_source *source)
struct stat buf;
struct burn_source_file *fs = source->data;
if (fs->fixed_size > 0)
return fs->fixed_size;
if (fstat(fs->datafd, &buf) == -1)
return (off_t) 0;
/* for now we keep it compatible to the old (int) return value */
if(buf.st_size >= 1308622848) /* 2 GB - 800 MB to prevent rollover */
return (off_t) 1308622848;
return (off_t) buf.st_size;
}
/* ts A70125 */
static int file_set_size(struct burn_source *source, off_t size)
{
struct burn_source_file *fs = source->data;
fs->fixed_size = size;
return 1;
}
struct burn_source *burn_file_source_new(const char *path, const char *subpath)
{
struct burn_source_file *fs;
struct burn_source *src;
int fd1, fd2 = 0;
int fd1 = -1, fd2 = -1;
if (!path)
return NULL;
fd1 = open(path, O_RDONLY);
if (fd1 == -1)
return NULL;
if (subpath) {
if (subpath != NULL) {
fd2 = open(subpath, O_RDONLY);
if (fd2 == -1) {
close(fd1);
@ -98,90 +119,494 @@ struct burn_source *burn_file_source_new(const char *path, const char *subpath)
}
}
fs = malloc(sizeof(struct burn_source_file));
fs->datafd = fd1;
if (subpath)
fs->subfd = fd2;
/* ts A70825 */
if (fs == NULL) {
failure:;
close(fd1);
if (fd2 >= 0)
close(fd2);
return NULL;
}
fs->datafd = fd1;
fs->subfd = fd2;
/* ts A70125 */
fs->fixed_size = 0;
src = burn_source_new();
/* ts A70825 */
if (src == NULL) {
free((char *) fs);
goto failure;
}
src->read = file_read;
if (subpath)
src->read_sub = file_read_sub;
src->get_size = file_size;
src->set_size = file_set_size;
src->free_data = file_free;
src->data = fs;
return src;
}
/* ------ provisory location for the new source subclass fd --------- */
static off_t fd_get_size(struct burn_source *source)
{
struct stat buf;
struct burn_source_fd *fs = source->data;
if (fs->fixed_size > 0)
return fs->fixed_size;
if (fstat(fs->datafd, &buf) == -1)
return (off_t) 0;
/* for now we keep it compatible to the old (int) return value */
if (buf.st_size >= 1308622848) /* 2 GB - 800 MB to prevent rollover */
return (off_t) 1308622848;
return buf.st_size;
}
static int fd_read(struct burn_source *source,
unsigned char *buffer,
int size)
{
struct burn_source_fd *fs = source->data;
return read_full_buffer(fs->datafd, buffer, size);
}
static int fd_read_sub(struct burn_source *source,
unsigned char *buffer,
int size)
{
struct burn_source_fd *fs = source->data;
return read_full_buffer(fs->subfd, buffer, size);
}
static void fd_free_data(struct burn_source *source)
{
struct burn_source_fd *fs = source->data;
close(fs->datafd);
if (source->read_sub)
close(fs->subfd);
free(fs);
}
/* ts A70126 : removed class burn_source_fd in favor of burn_source_file */
struct burn_source *burn_fd_source_new(int datafd, int subfd, off_t size)
{
struct burn_source_fd *fs;
struct burn_source_file *fs;
struct burn_source *src;
if (datafd == -1)
return NULL;
fs = malloc(sizeof(struct burn_source_fd));
fs = malloc(sizeof(struct burn_source_file));
if (fs == NULL) /* ts A70825 */
return NULL;
fs->datafd = datafd;
fs->subfd = subfd;
fs->fixed_size = size;
src = burn_source_new();
src->read = fd_read;
/* ts A70825 */
if (src == NULL) {
free((char *) fs);
return NULL;
}
src->read = file_read;
if(subfd != -1)
src->read = fd_read_sub;
src->get_size = fd_get_size;
src->free_data = fd_free_data;
src->read_sub = file_read_sub;
src->get_size = file_size;
src->set_size = file_set_size;
src->free_data = file_free;
src->data = fs;
return src;
}
/* ts A71003 */
/* ------------------------------ fifo --------------------------- */
/* The fifo mechanism consists of a burn_source proxy which is here,
a thread management team which is located in async.c,
and a synchronous shoveller which is here.
*/
static int fifo_sleep(int flag)
{
static struct timespec sleeptime = { 0, 50000000}; /* 50 ms */
return nanosleep(&sleeptime, NULL);
}
static int fifo_read(struct burn_source *source,
unsigned char *buffer,
int size)
{
struct burn_source_fifo *fs = source->data;
int ret, todo, rpos, bufsize, diff;
if (fs->end_of_consumption) {
/* ??? msg: reading has been ended already */;
return 0;
}
if (fs->is_started == 0) {
ret = burn_fifo_start(source, 0);
if (ret <= 0) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020152,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Cannot start fifo thread", 0, 0);
fs->end_of_consumption = 1;
return -1;
}
fs->is_started = 1;
}
if (size == 0)
return 0;
/* Reading from the ring buffer */
/* This needs no mutex because each volatile variable has one thread
which may write and the other which only reads and is aware of
volatility.
The feeder of the ringbuffer is in burn_fifo_source_shoveller().
*/
todo = size;
bufsize = fs->chunksize * fs->chunks;
while (todo > 0) {
/* readpos is not volatile here , writepos is volatile */
rpos = fs->buf_readpos;
while (rpos == fs->buf_writepos) {
if (fs->end_of_input)
break;
if (fs->input_error) {
if (todo < size) /* deliver partial buffer */
break;
fs->end_of_consumption = 1;
libdax_msgs_submit(libdax_messenger, -1,
0x00020154,
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
"Forwarded input error ends output", 0, 0);
return -1;
}
fifo_sleep(0);
}
diff = fs->buf_writepos - rpos; /* read volatile only once */
if (diff == 0)
break;
if (diff > 0)
/* diff bytes are available */;
else
/* at least (bufsize - rpos) bytes are available */
diff = bufsize - rpos;
if (diff > todo)
diff = todo;
memcpy(buffer, fs->buf+(size-todo)+rpos, diff);
fs->buf_readpos += diff;
if (fs->buf_readpos >= bufsize)
fs->buf_readpos = 0;
todo -= diff;
}
if (size - todo <= 0)
fs->end_of_consumption = 1;
else
fs->out_counter += size - todo;
/*
fprintf(stderr,
"libburn_EXPERIMENTAL: read= %d , pos= %d , out_count= %.f\n",
(size - todo), fs->buf_readpos, (double) fs->out_counter);
*/
return (size - todo);
}
static off_t fifo_get_size(struct burn_source *source)
{
struct burn_source_fifo *fs = source->data;
return fs->inp->get_size(fs->inp);
}
static int fifo_set_size(struct burn_source *source, off_t size)
{
struct burn_source_fifo *fs = source->data;
return fs->inp->set_size(fs->inp, size);
}
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);
free((char *) fs);
}
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;
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_is_valid = 1;
bufsize = fs->chunksize * fs->chunks;
while (!fs->end_of_consumption) {
/* wait for enough buffer space available */
wpos = fs->buf_writepos;
while (1) {
rpos = fs->buf_readpos;
diff = rpos - wpos;
trans_end = 0;
if (diff == 0)
free_bytes = bufsize - 1;
else if (diff > 0)
free_bytes = diff - 1;
else {
free_bytes = (bufsize - wpos) + rpos - 1;
if (bufsize - wpos < fs->chunksize)
trans_end = 1;
}
if (free_bytes >= fs->chunksize)
break;
fifo_sleep(0);
}
/* prepare the receiving memory */
bufpt = fs->buf + wpos;
if (trans_end) {
bufpt = calloc(fs->chunksize, 1);
if (bufpt == NULL) {
libdax_msgs_submit(libdax_messenger, -1,
0x00000003,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Out of virtual memory", 0, 0);
fs->input_error = ENOMEM;
break;
}
}
/* Obtain next chunk */
if (fs->inp->read != NULL)
ret = fs->inp->read(fs->inp,
(unsigned char *) bufpt, fs->chunksize);
else
ret = fs->inp->read_xt( fs->inp,
(unsigned char *) bufpt, fs->chunksize);
if (ret > 0)
fs->in_counter += ret;
else if (ret == 0)
break; /* EOF */
else {
libdax_msgs_submit(libdax_messenger, -1, 0x00020153,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Read error on fifo input", errno, 0);
fs->input_error = errno;
if(errno == 0)
fs->input_error = EIO;
break;
}
/* activate read chunk */
if (ret > fs->chunksize) /* beware of ill custom burn_source */
ret = fs->chunksize;
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);
if (ret >= bufsize - wpos)
fs->buf_writepos = ret - (bufsize - wpos);
else
fs->buf_writepos += ret;
} else if (fs->buf_writepos + ret == bufsize)
fs->buf_writepos = 0;
else
fs->buf_writepos += ret;
/*
fprintf(stderr, "[%2.2d%%] ",
(int) (100.0 - 100.0 * ((double) free_bytes) /
(double) bufsize));
fprintf(stderr,
"libburn_EXPERIMENTAL: writepos= %d ,in_count = %.f\n",
fs->buf_writepos, (double) fs->in_counter);
*/
}
if (!fs->end_of_consumption)
fs->end_of_input = 1;
/* wait for end of reading by consumer */;
while (fs->buf_readpos != fs->buf_writepos && !fs->end_of_consumption)
fifo_sleep(0);
/* destroy ring buffer */;
if (!fs->end_of_consumption)
fs->end_of_consumption = 2; /* Claim stop of consumption */
/* This is not prone to race conditions because either the consumer
indicated hangup by fs->end_of_consumption = 1 or the consumer set
fs->buf_readpos to a value indicating the buffer is empty.
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. */
fs->buf = NULL;
fs->thread_handle= NULL;
fs->thread_is_valid = 0;
return (fs->input_error == 0);
}
int burn_fifo_cancel(struct burn_source *source)
{
struct burn_source_fifo *fs = source->data;
burn_source_cancel(fs->inp);
return(1);
}
struct burn_source *burn_fifo_source_new(struct burn_source *inp,
int chunksize, int chunks, int flag)
{
struct burn_source_fifo *fs;
struct burn_source *src;
if (((double) chunksize) * ((double) chunks) > 1024.0*1024.0*1024.0) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020155,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Desired fifo buffer too large (> 1GB)", 0, 0);
return NULL;
}
if (chunksize < 1 || chunks < 2) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020156,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Desired fifo buffer too small", 0, 0);
return NULL;
}
fs = malloc(sizeof(struct burn_source_fifo));
if (fs == NULL)
return NULL;
fs->is_started = 0;
fs->thread_handle = NULL;
fs->thread_pid = 0;
fs->thread_is_valid = 0;
fs->inp = NULL; /* set later */
fs->chunksize = chunksize;
fs->chunks = chunks;
fs->buf = NULL;
fs->buf_writepos = fs->buf_readpos = 0;
fs->end_of_input = 0;
fs->input_error = 0;
fs->end_of_consumption = 0;
fs->in_counter = fs->out_counter = 0;
src = burn_source_new();
if (src == NULL) {
free((char *) fs);
return NULL;
}
src->read = NULL;
src->read_sub = NULL;
src->get_size = fifo_get_size;
src->set_size = fifo_set_size;
src->free_data = fifo_free;
src->data = fs;
src->version= 1;
src->read_xt = fifo_read;
src->cancel= burn_fifo_cancel;
fs->inp = inp;
inp->refcount++; /* make sure inp lives longer than src */
return src;
}
/* ts A71003 : API */
int burn_fifo_inquire_status(struct burn_source *source,
int *size, int *free_bytes, char **status_text)
{
struct burn_source_fifo *fs = source->data;
int ret = 0, diff, wpos, rpos;
static char *(states[8]) = {
"standby", "active", "ending", "failing",
"unused", "abandoned", "ended", "aborted"};
*status_text = NULL;
*size = 0;
if (source->free_data != fifo_free) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020157,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"burn_source is not a fifo object", 0, 0);
return -1;
}
*size = fs->chunksize * fs->chunks;
rpos = fs->buf_readpos;
wpos = fs->buf_writepos;
diff = rpos - wpos;
if (diff == 0)
*free_bytes = *size - 1;
else if (diff > 0)
*free_bytes = diff - 1;
else
*free_bytes = (*size - wpos) + rpos - 1;
ret = 0;
if (fs->end_of_consumption > 0)
ret |= 4;
if (fs->input_error)
ret |= 3;
else if (fs->end_of_input)
ret |= 2;
else if(fs->buf != NULL)
ret |= 1;
*status_text = states[ret];
return ret;
}
int burn_fifo_peek_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;
/* Eventually start fifo thread by reading 0 bytes */
ret = fifo_read(source, (unsigned char *) NULL, 0);
if (ret<0)
return 0;
/* 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 (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;
}
if(size - free_bytes >= bufsize) {
/* <<<
fprintf(stderr,
"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 (ret&2) { /* input has ended, not enough data arrived */
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;
}
usleep(100000);
wait_count++;
/* <<<
if(wait_count%10==0)
fprintf(stderr,
"libburn_DEBUG: waiting cycle %d : fifo %s , %d bytes\n",
wait_count, status_text, size - free_bytes);
*/
}
return(0);
}

View File

@ -5,18 +5,59 @@
struct burn_source_file
{
int datafd;
int subfd;
};
char magic[4];
/* ------ provisory location for the new source subclass fd --------- */
struct burn_source_fd
{
int datafd;
int subfd;
off_t fixed_size;
};
/* ts A70126 : burn_source_file obsoleted burn_source_fd */
/* ts A70930 */
struct burn_source_fifo {
char magic[4];
/* The fifo stays inactive and unequipped with eventual resources
until its read() method is called for the first time.
Only then burn_fifo_start() gets called, allocates the complete
resources, starts a thread with burn_fifo_source_shuffler()
which shuffles data and finally destroys the resources.
This late start is to stay modest in case of multiple tracks
in one disc.
*/
int is_started;
void *thread_handle; /* actually a pointer to a thread_t */
int thread_pid;
int thread_is_valid;
/* the burn_source for which this fifo is acting as proxy */
struct burn_source *inp;
/* <<< up to now it was only a pipe. This is on its way out. */
int outlet[2];
/* The ring buffer mechanism */
int chunksize;
int chunks;
char *buf;
volatile int buf_writepos;
volatile int buf_readpos;
volatile int end_of_input;
volatile int input_error;
volatile int end_of_consumption;
off_t in_counter;
off_t out_counter;
};
/** The worker behind the fifo thread.
Gets started from burn_fifo_start() in async.c
*/
int burn_fifo_source_shoveller(struct burn_source *source, int flag);
#endif /* LIBBURN__FILE_H */

View File

@ -8,12 +8,18 @@
#include <stdio.h>
#include <signal.h>
#include <string.h>
#include <stdlib.h>
/* ts A70928 : init.h is for others, not for init .c
#include "init.h"
*/
#include "sg.h"
#include "error.h"
#include "libburn.h"
#include "drive.h"
#include "transport.h"
/* ts A60825 : The storage location for back_hacks.h variables. */
#define BURN_BACK_HACKS_INIT 1
@ -26,9 +32,22 @@ struct libdax_msgs *libdax_messenger= NULL;
int burn_running = 0;
/* ts A60813 : wether to use O_EXCL and/or O_NONBLOCK in libburn/sg.c */
/* ts A60813 : Linux: wether to use O_EXCL on open() of device files */
int burn_sg_open_o_excl = 1;
/* ts A70403 : Linux: wether to use fcntl(,F_SETLK,)
after open() of device files */
int burn_sg_fcntl_f_setlk = 1;
/* ts A70314 : Linux: what device family to use :
0= default family
1= sr
2= scd
(3= st)
4= sg
*/
int burn_sg_use_family = 0;
/* O_NONBLOCK was hardcoded in enumerate_ata() which i hardly use.
For enumerate_sg() it seems ok.
So it should stay default mode until enumerate_ata() without O_NONBLOCK
@ -40,7 +59,6 @@ int burn_sg_open_o_nonblock = 1;
to unconditional abort of the process */
int burn_sg_open_abort_busy = 0;
/* ts A61002 */
#include "cleanup.h"
@ -48,6 +66,14 @@ 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;
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;
/* ts A70223 : wether implemented untested profiles are supported */
int burn_support_untested_profiles = 0;
/* ts A60925 : ticket 74 */
@ -73,6 +99,7 @@ int burn_initialize(void)
if (burn_running)
return 1;
burn_support_untested_profiles = 0;
ret = burn_msgs_initialize();
if (ret <= 0)
return 0;
@ -89,11 +116,12 @@ void burn_finish(void)
/* ts A61007 */
/* burn_wait_all(); */
if (!burn_drives_are_clear()) {
if (!burn_drives_are_clear(0)) {
libdax_msgs_submit(libdax_messenger, -1, 0x00020107,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Drive is busy on attempt to shut down library", 0, 0);
return;
LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
"A drive is still busy on shutdown of library", 0, 0);
usleep(1000001);
burn_abort(4440, burn_abort_pacifier, abort_message_prefix);
}
/* ts A60904 : ticket 62, contribution by elmom : name addon "_all" */
@ -114,10 +142,11 @@ void burn_preset_device_open(int exclusive, int blocking, int abort_on_busy)
/* a ssert(burn_running); */
if (!burn_running)
return;
burn_sg_open_o_excl= exclusive;
burn_sg_open_o_nonblock= !blocking;
burn_sg_open_abort_busy= !!abort_on_busy;
burn_sg_open_o_excl = exclusive & 3;
burn_sg_fcntl_f_setlk = !!(exclusive & 32);
burn_sg_use_family = (exclusive >> 2) & 7;
burn_sg_open_o_nonblock = !blocking;
burn_sg_open_abort_busy = !!abort_on_busy;
}
@ -181,6 +210,8 @@ int burn_msgs_obtain(char *minimum_severity,
ret = libdax_msgs__text_to_sev(minimum_severity, &minimum_sevno, 0);
if (ret <= 0)
return 0;
if (libdax_messenger == NULL)
return 0;
ret = libdax_msgs_obtain(libdax_messenger, &item, minimum_sevno,
LIBDAX_MSGS_PRIO_ZERO, 0);
if (ret <= 0)
@ -207,10 +238,124 @@ ex:
return ret;
}
/* ts A70922 : API */
int burn_msgs_submit(int error_code, char msg_text[], int os_errno,
char severity[], struct burn_drive *d)
{
int ret, sevno, global_index = -1;
ret = libdax_msgs__text_to_sev(severity, &sevno, 0);
if (ret <= 0)
sevno = LIBDAX_MSGS_SEV_ALL;
if (error_code <= 0) {
switch(sevno) {
case LIBDAX_MSGS_SEV_ABORT: error_code = 0x00040000;
break; case LIBDAX_MSGS_SEV_FATAL: error_code = 0x00040001;
break; case LIBDAX_MSGS_SEV_SORRY: error_code = 0x00040002;
break; case LIBDAX_MSGS_SEV_WARNING: error_code = 0x00040003;
break; case LIBDAX_MSGS_SEV_HINT: error_code = 0x00040004;
break; case LIBDAX_MSGS_SEV_NOTE: error_code = 0x00040005;
break; case LIBDAX_MSGS_SEV_UPDATE: error_code = 0x00040006;
break; case LIBDAX_MSGS_SEV_DEBUG: error_code = 0x00040007;
break; default: error_code = 0x00040008;
}
}
if (d != NULL)
global_index = d->global_index;
ret = libdax_msgs_submit(libdax_messenger, global_index, error_code,
sevno, LIBDAX_MSGS_PRIO_HIGH, msg_text, os_errno, 0);
return ret;
}
/* ts A71016 API */
int burn_text_to_sev(char *severity_name, int *sevno, int flag)
{
int ret;
ret = libdax_msgs__text_to_sev(severity_name, sevno, 0);
return ret;
}
/* ts A80202 API */
int burn_sev_to_text(int severity_number, char **severity_name, int flag)
{
int ret;
ret = libdax_msgs__sev_to_text(severity_number, severity_name, 0);
return ret;
}
int burn_builtin_abort_handler(void *handle, int signum, int flag)
{
if(getpid() != abort_control_pid)
#define Libburn_new_thread_signal_handleR 1
/*
#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);
#endif
/* 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
yield at least 1 if any thread calls this function.
*/
burn_global_abort_level++;
burn_global_abort_signum= signum;
if(getpid() != abort_control_pid) {
#ifdef Libburn_new_thread_signal_handleR
ret = burn_drive_find_by_thread_pid(&d, getpid());
if (ret > 0 && d->busy == BURN_DRIVE_WRITING) {
/* This is an active writer thread */
#ifdef Libburn_signal_handler_verbouS
fprintf(stderr, "libburn_ABORT: pid %d found drive busy with writing, (level= %d)\n", (int) getpid(), burn_global_abort_level);
#endif
d->sync_cache(d);
/* >>> perform a more qualified end of burn process */;
d->busy = BURN_DRIVE_IDLE;
if (burn_global_abort_level > 0) {
/* control process did not show up yet */
#ifdef Libburn_signal_handler_verbouS
fprintf(stderr, "libburn_ABORT: pid %d sending signum %d to pid %d\n", (int) getpid(), (int) signum, (int) abort_control_pid);
#endif
kill(abort_control_pid, signum);
}
#ifdef Libburn_signal_handler_verbouS
fprintf(stderr, "libburn_ABORT: pid %d signum %d returning -2\n", (int) getpid(), (int) signum);
#endif
return -2;
} else {
usleep(1000000); /* calm down */
return -2;
}
#else
usleep(1000000); /* calm down */
return -2;
#endif /* ! Libburn_new_thread_signal_handleR */
}
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);
@ -218,10 +363,13 @@ int burn_builtin_abort_handler(void *handle, int signum, int flag)
"%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,
"\n%sABORT : Program done. Even if you do not see a shell prompt.\n\n",
abort_message_prefix);
burn_global_abort_level = -2;
return(1);
}
@ -240,7 +388,29 @@ void burn_set_signal_handling(void *handle, burn_abort_handler_t 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();
abort_control_pid = getpid();
Cleanup_set_handlers(handle, (Cleanup_app_handler_T) handler, mode|4);
burn_global_signal_handle = handle;
burn_global_signal_handler = handler;
}
/* ts A70223 : API */
void burn_allow_untested_profiles(int yes)
{
burn_support_untested_profiles = !!yes;
}
/* ts A70915 : API */
int burn_set_messenger(void *messenger)
{
struct libdax_msgs *pt;
if (libdax_msgs_refer(&pt, messenger, 0) <= 0)
return 0;
libdax_msgs_destroy(&libdax_messenger, 0);
libdax_messenger = (struct libdax_msgs *) pt;
return 1;
}

View File

@ -5,4 +5,17 @@
extern int burn_running;
/** Indicator for burn_drive_get_status() wether a signal hit parts of the
thread team.
0= all works well ,
1 to 5 = waiting for eventual signal on control thread
> 5 = do abort now
-1 = control thread has been informed
*/
extern volatile int burn_global_abort_level;
extern int burn_global_abort_signum;
extern void *burn_global_signal_handle;
extern burn_abort_handler_t burn_global_signal_handler;
#endif /* BURN__INIT_H */

File diff suppressed because it is too large Load Diff

View File

@ -34,7 +34,7 @@ int libdax_audioxtr_new(struct libdax_audioxtr **xtr, char *path, int flag)
if(o==NULL)
return(-1);
strncpy(o->path,path,LIBDAX_AUDIOXTR_STRLEN-1);
o->path[LIBDAX_AUDIOXTR_STRLEN]= 0;
o->path[LIBDAX_AUDIOXTR_STRLEN-1]= 0;
o->fd= -1;
strcpy(o->fmt,"unidentified");
o->fmt_info[0]= 0;

View File

@ -1,7 +1,8 @@
/* libdax_msgs
Message handling facility of libdax.
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
Copyright (C) 2006 - 2009 Thomas Schmitt <scdbackup@gmx.net>,
provided under GPL version 2
*/
#include <stdio.h>
@ -39,7 +40,7 @@ static int libdax_msgs_item_new(struct libdax_msgs_item **item,
if(ret==0)
o->timestamp= tv.tv_sec+0.000001*tv.tv_usec;
o->process_id= getpid();
o->driveno= -1;
o->origin= -1;
o->severity= LIBDAX_MSGS_SEV_ALL;
o->priority= LIBDAX_MSGS_PRIO_ZERO;
o->error_code= 0;
@ -108,12 +109,12 @@ int libdax_msgs_item_get_msg(struct libdax_msgs_item *item,
int libdax_msgs_item_get_origin(struct libdax_msgs_item *item,
double *timestamp, pid_t *process_id, int *driveno,
double *timestamp, pid_t *process_id, int *origin,
int flag)
{
*timestamp= item->timestamp;
*process_id= item->process_id;
*driveno= item->driveno;
*origin= item->origin;
return(1);
}
@ -137,6 +138,7 @@ int libdax_msgs_new(struct libdax_msgs **m, int flag)
(*m)= o= (struct libdax_msgs *) malloc(sizeof(struct libdax_msgs));
if(o==NULL)
return(-1);
o->refcount= 1;
o->oldest= NULL;
o->youngest= NULL;
o->count= 0;
@ -152,43 +154,6 @@ int libdax_msgs_new(struct libdax_msgs **m, int flag)
}
int libdax_msgs_destroy(struct libdax_msgs **m, int flag)
{
struct libdax_msgs *o;
struct libdax_msgs_item *item, *next_item;
o= *m;
if(o==NULL)
return(0);
#ifndef LIBDAX_MSGS_SINGLE_THREADED
if(pthread_mutex_destroy(&(o->lock_mutex))!=0) {
pthread_mutex_unlock(&(o->lock_mutex));
pthread_mutex_destroy(&(o->lock_mutex));
}
#endif
for(item= o->oldest; item!=NULL; item= next_item) {
next_item= item->next;
libdax_msgs_item_destroy(&item,0);
}
free((char *) o);
*m= NULL;
return(1);
}
int libdax_msgs_set_severities(struct libdax_msgs *m, int queue_severity,
int print_severity, char *print_id, int flag)
{
m->queue_severity= queue_severity;
m->print_severity= print_severity;
strncpy(m->print_id,print_id,80);
m->print_id[80]= 0;
return(1);
}
static int libdax_msgs_lock(struct libdax_msgs *m, int flag)
{
@ -219,6 +184,65 @@ static int libdax_msgs_unlock(struct libdax_msgs *m, int flag)
}
int libdax_msgs_destroy(struct libdax_msgs **m, int flag)
{
struct libdax_msgs *o;
struct libdax_msgs_item *item, *next_item;
o= *m;
if(o==NULL)
return(0);
if(o->refcount > 1) {
if(libdax_msgs_lock(*m,0)<=0)
return(-1);
o->refcount--;
libdax_msgs_unlock(*m,0);
*m= NULL;
return(1);
}
#ifndef LIBDAX_MSGS_SINGLE_THREADED
if(pthread_mutex_destroy(&(o->lock_mutex))!=0) {
pthread_mutex_unlock(&(o->lock_mutex));
pthread_mutex_destroy(&(o->lock_mutex));
}
#endif
for(item= o->oldest; item!=NULL; item= next_item) {
next_item= item->next;
libdax_msgs_item_destroy(&item,0);
}
free((char *) o);
*m= NULL;
return(1);
}
int libdax_msgs_refer(struct libdax_msgs **pt, struct libdax_msgs *m, int flag)
{
if(libdax_msgs_lock(m,0)<=0)
return(0);
m->refcount++;
*pt= m;
libdax_msgs_unlock(m,0);
return(1);
}
int libdax_msgs_set_severities(struct libdax_msgs *m, int queue_severity,
int print_severity, char *print_id, int flag)
{
if(libdax_msgs_lock(m,0)<=0)
return(0);
m->queue_severity= queue_severity;
m->print_severity= print_severity;
strncpy(m->print_id,print_id,80);
m->print_id[80]= 0;
libdax_msgs_unlock(m,0);
return(1);
}
int libdax_msgs__text_to_sev(char *severity_name, int *severity,
int flag)
{
@ -228,6 +252,10 @@ int libdax_msgs__text_to_sev(char *severity_name, int *severity,
*severity= LIBDAX_MSGS_SEV_ABORT;
else if(strncmp(severity_name,"FATAL",5)==0)
*severity= LIBDAX_MSGS_SEV_FATAL;
else if(strncmp(severity_name,"FAILURE",7)==0)
*severity= LIBDAX_MSGS_SEV_FAILURE;
else if(strncmp(severity_name,"MISHAP",6)==0)
*severity= LIBDAX_MSGS_SEV_MISHAP;
else if(strncmp(severity_name,"SORRY",5)==0)
*severity= LIBDAX_MSGS_SEV_SORRY;
else if(strncmp(severity_name,"WARNING",7)==0)
@ -240,10 +268,12 @@ int libdax_msgs__text_to_sev(char *severity_name, int *severity,
*severity= LIBDAX_MSGS_SEV_UPDATE;
else if(strncmp(severity_name,"DEBUG",5)==0)
*severity= LIBDAX_MSGS_SEV_DEBUG;
else if(strncmp(severity_name,"ERRFILE",7)==0)
*severity= LIBDAX_MSGS_SEV_ERRFILE;
else if(strncmp(severity_name,"ALL",3)==0)
*severity= LIBDAX_MSGS_SEV_ALL;
else {
*severity= LIBDAX_MSGS_SEV_NEVER;
*severity= LIBDAX_MSGS_SEV_ALL;
return(0);
}
return(1);
@ -254,8 +284,7 @@ int libdax_msgs__sev_to_text(int severity, char **severity_name,
int flag)
{
if(flag&1) {
*severity_name=
"NEVER\nABORT\nFATAL\nSORRY\nWARNING\nHINT\nNOTE\nUPDATE\nDEBUG\nALL";
*severity_name= "NEVER\nABORT\nFATAL\nFAILURE\nMISHAP\nSORRY\nWARNING\nHINT\nNOTE\nUPDATE\nDEBUG\nERRFILE\nALL";
return(1);
}
*severity_name= "";
@ -265,6 +294,10 @@ int libdax_msgs__sev_to_text(int severity, char **severity_name,
*severity_name= "ABORT";
else if(severity>=LIBDAX_MSGS_SEV_FATAL)
*severity_name= "FATAL";
else if(severity>=LIBDAX_MSGS_SEV_FAILURE)
*severity_name= "FAILURE";
else if(severity>=LIBDAX_MSGS_SEV_MISHAP)
*severity_name= "MISHAP";
else if(severity>=LIBDAX_MSGS_SEV_SORRY)
*severity_name= "SORRY";
else if(severity>=LIBDAX_MSGS_SEV_WARNING)
@ -277,6 +310,8 @@ int libdax_msgs__sev_to_text(int severity, char **severity_name,
*severity_name= "UPDATE";
else if(severity>=LIBDAX_MSGS_SEV_DEBUG)
*severity_name= "DEBUG";
else if(severity>=LIBDAX_MSGS_SEV_ERRFILE)
*severity_name= "ERRFILE";
else if(severity>=LIBDAX_MSGS_SEV_ALL)
*severity_name= "ALL";
else {
@ -287,7 +322,7 @@ int libdax_msgs__sev_to_text(int severity, char **severity_name,
}
int libdax_msgs_submit(struct libdax_msgs *m, int driveno, int error_code,
int libdax_msgs_submit(struct libdax_msgs *m, int origin, int error_code,
int severity, int priority, char *msg_text,
int os_errno, int flag)
{
@ -325,7 +360,7 @@ int libdax_msgs_submit(struct libdax_msgs *m, int driveno, int error_code,
ret= libdax_msgs_item_new(&item,m->youngest,0);
if(ret<=0)
goto failed;
item->driveno= driveno;
item->origin= origin;
item->error_code= error_code;
item->severity= severity;
item->priority= priority;

View File

@ -1,7 +1,8 @@
/* libdax_msgs
Message handling facility of libdax.
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
Copyright (C) 2006-2009 Thomas Schmitt <scdbackup@gmx.net>,
provided under GPL version 2
*/
@ -22,7 +23,7 @@ struct libdax_msgs_item {
double timestamp;
pid_t process_id;
int driveno;
int origin;
int severity;
int priority;
@ -42,6 +43,8 @@ struct libdax_msgs_item {
struct libdax_msgs {
int refcount;
struct libdax_msgs_item *oldest;
struct libdax_msgs_item *youngest;
int count;
@ -67,6 +70,31 @@ struct libdax_msgs {
#ifndef LIBDAX_MSGS_H_INTERNAL
/* Architectural aspects */
/*
libdax_msgs is designed to serve in libraries which want to offer their
applications a way to control the output of library messages. It shall be
incorporated by an owner, i.e. a software entity which encloses the code
of the .c file.
Owner of libdax_msgs is libburn. A fully compatible variant named libiso_msgs
is owned by libisofs and can get generated by a script of the libburn
project: libburn/libdax_msgs_to_xyz_msgs.sh .
Reason: One cannot link two owners of the same variant together because
both would offer the same functions to the linker. For that situation one
has to create a compatible variant as it is done for libisofs.
Compatible variants may get plugged together by call combinations like
burn_set_messenger(iso_get_messenger());
A new variant would demand a _set_messenger() function if it has to work
with libisofs. If only libburn is planned as link partner then a simple
_get_messenger() does suffice.
Take care to shutdown libburn before its provider of the *_msgs object
gets shut down.
*/
/* Public Opaque Handles */
/** A pointer to this is a opaque handle to a message handling facility */
@ -85,13 +113,26 @@ struct libdax_msgs_item;
/* It is well advisable to let applications select severities via strings and
forwarded functions libdax_msgs__text_to_sev(), libdax_msgs__sev_to_text().
These macros are for use by libdax/libburn only.
These macros are for use by the owner of libdax_msgs.
*/
/** Use this to get messages of any severity. Do not use for submitting.
*/
#define LIBDAX_MSGS_SEV_ALL 0x00000000
/** Messages of this severity shall transport plain disk file paths
whenever an event of severity SORRY or above is related with an
individual disk file.
No message text shall be added to the file path. The ERRFILE message
shall be issued before the human readable message which carries the
true event severity. That message should contain the file path so it
can be found by strstr(message, path)!=NULL.
The error code shall be the same as with the human readable message.
*/
#define LIBDAX_MSGS_SEV_ERRFILE 0x08000000
/** Debugging messages not to be visible to normal users by default
*/
#define LIBDAX_MSGS_SEV_DEBUG 0x10000000
@ -112,15 +153,70 @@ struct libdax_msgs_item;
*/
#define LIBDAX_MSGS_SEV_WARNING 0x50000000
/** Non-fatal error messages indicating that parts of the action failed
but processing will/should go on
/** Non-fatal error messages indicating that parts of an action failed but
processing may go on if one accepts deviations from the desired result.
SORRY may also be the severity for incidents which are severe enough
for FAILURE but happen within already started irrevocable actions,
like ISO image generation. A precondition for such a severity ease is
that the action can be continued after the incident.
See below MISHAP for what xorriso would need instead of this kind of SORRY
and generates for itself in case of libisofs image generation.
E.g.: A pattern yields no result.
A speed setting cannot be made.
A libisofs input file is inaccessible during image generation.
After SORRY a function should try to go on if that makes any sense
and if no threshold prescribes abort on SORRY. The function should
nevertheless indicate some failure in its return value.
It should - but it does not have to.
*/
#define LIBDAX_MSGS_SEV_SORRY 0x60000000
/** An error message which puts the whole operation of libdax in question
/** A FAILURE (see below) which can be tolerated during long lasting
operations just because they cannot simply be stopped or revoked.
xorriso converts libisofs SORRY messages issued during image generation
into MISHAP messages in order to allow its evaluators to distinguish
image generation problems from minor image composition problems.
E.g.:
A libisofs input file is inaccessible during image generation.
After a MISHAP a function should behave like after SORRY.
*/
#define LIBDAX_MSGS_SEV_MISHAP 0x64000000
/** Non-fatal error indicating that an important part of an action failed and
that only a new setup of preconditions will give hope for sufficient
success.
E.g.: No media is inserted in the output drive.
No write mode can be found for inserted media.
A libisofs input file is inaccessible during grafting.
After FAILURE a function should end with a return value indicating failure.
It is at the discretion of the function whether it ends immediately in any
case or whether it tries to go on if the eventual threshold allows.
*/
#define LIBDAX_MSGS_SEV_FAILURE 0x68000000
/** An error message which puts the whole operation of the program in question
E.g.: Not enough memory for essential temporary objects.
Irregular errors from resources.
Programming errors (soft assert).
After FATAL a function should end very soon with a return value
indicating severe failure.
*/
#define LIBDAX_MSGS_SEV_FATAL 0x70000000
/** A message from an abort handler which will finally finish libburn
*/
#define LIBDAX_MSGS_SEV_ABORT 0x71000000
@ -133,7 +229,7 @@ struct libdax_msgs_item;
/* Registered Priorities */
/* Priorities are to be used by libburn/libdax only. */
/* Priorities are to be selected by the programmers and not by the user. */
#define LIBDAX_MSGS_PRIO_ZERO 0x00000000
#define LIBDAX_MSGS_PRIO_LOW 0x10000000
@ -145,12 +241,23 @@ struct libdax_msgs_item;
#define LIBDAX_MSGS_PRIO_NEVER 0x7fffffff
/* Origin numbers of libburn drives may range from 0 to 1048575 */
#define LIBDAX_MSGS_ORIGIN_DRIVE_BASE 0
#define LIBDAX_MSGS_ORIGIN_DRIVE_TOP 0xfffff
/* Origin numbers of libisofs images may range from 1048575 to 2097152 */
#define LIBDAX_MSGS_ORIGIN_IMAGE_BASE 0x100000
#define LIBDAX_MSGS_ORIGIN_IMAGE_TOP 0x1fffff
/* Public Functions */
/* Calls initiated from inside libdax/libburn */
/* Calls initiated from inside the direct owner (e.g. from libburn) */
/** Create new empty message handling facility with queue.
/** Create new empty message handling facility with queue and issue a first
official reference to it.
@param flag Bitfield for control purposes (unused yet, submit 0)
@return >0 success, <=0 failure
*/
@ -159,18 +266,37 @@ int libdax_msgs_new(struct libdax_msgs **m, int flag);
/** Destroy a message handling facility and all its eventual messages.
The submitted pointer gets set to NULL.
Actually only the last destroy call of all offical references to the object
will really dispose it. All others just decrement the reference counter.
Call this function only with official reference pointers obtained by
libdax_msgs_new() or libdax_msgs_refer(), and only once per such pointer.
@param flag Bitfield for control purposes (unused yet, submit 0)
@return 1 for success, 0 for pointer to NULL
@return 1 for success, 0 for pointer to NULL, -1 for fatal error
*/
int libdax_msgs_destroy(struct libdax_msgs **m, int flag);
/** Create an official reference to an existing libdax_msgs object. The
references keep the object alive at least until it is released by
a matching number of destroy calls. So each reference MUST be revoked
by exactly one call to libdax_msgs_destroy().
@param pt The pointer to be set and registered
@param m A pointer to the existing object
@param flag Bitfield for control purposes (unused yet, submit 0)
@return 1 for success, 0 for failure
*/
int libdax_msgs_refer(struct libdax_msgs **pt, struct libdax_msgs *o, int flag);
/** Submit a message to a message handling facility.
@param driveno libdax drive number. Use -1 if no number is known.
@param origin program specific identification number of the originator of
a message. E.g. drive number. Programs should have an own
range of origin numbers. See above LIBDAX_MSGS_ORIGIN_*_BASE
Use -1 if no number is known.
@param error_code Unique error code. Use only registered codes. See below.
The same unique error_code may be issued at different
occasions but those should be equivalent out of the view
of a libdax application. (E.g. "cannot open ATA drive"
of a libdax_msgs application. (E.g. "cannot open ATA drive"
versus "cannot open SCSI drive" would be equivalent.)
@param severity The LIBDAX_MSGS_SEV_* of the event.
@param priority The LIBDAX_MSGS_PRIO_* number of the event.
@ -179,12 +305,13 @@ int libdax_msgs_destroy(struct libdax_msgs **m, int flag);
@param flag Bitfield for control purposes (unused yet, submit 0)
@return 1 on success, 0 on rejection, <0 for severe errors
*/
int libdax_msgs_submit(struct libdax_msgs *m, int driveno, int error_code,
int libdax_msgs_submit(struct libdax_msgs *m, int origin, int error_code,
int severity, int priority, char *msg_text,
int os_errno, int flag);
/* Calls from applications (to be forwarded by libdax/libburn) */
/* Calls from applications (to be forwarded by direct owner) */
/** Convert a registered severity number into a severity name
@ -255,7 +382,7 @@ int libdax_msgs_item_get_msg(struct libdax_msgs_item *item,
@return 1 on success, 0 on invalid item, <0 for servere errors
*/
int libdax_msgs_item_get_origin(struct libdax_msgs_item *item,
double *timestamp, pid_t *process_id, int *driveno,
double *timestamp, pid_t *process_id, int *origin,
int flag);
@ -275,7 +402,7 @@ int libdax_msgs_item_get_rank(struct libdax_msgs_item *item,
Format: error_code (LIBDAX_MSGS_SEV_*,LIBDAX_MSGS_PRIO_*) = explanation
If no severity or priority are fixely associates, use "(,)".
If no severity or priority are fixely associated, use "(,)".
------------------------------------------------------------------------------
Range "libdax_msgs" : 0x00000000 to 0x0000ffff
@ -283,6 +410,7 @@ Range "libdax_msgs" : 0x00000000 to 0x0000ffff
0x00000000 (ALL,ZERO) = Initial setting in new libdax_msgs_item
0x00000001 (DEBUG,ZERO) = Test error message
0x00000002 (DEBUG,ZERO) = Debugging message
0x00000003 (FATAL,HIGH) = Out of virtual memory
------------------------------------------------------------------------------
@ -299,11 +427,15 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
0x00020002 (SORRY,HIGH) = Encountered error when closing drive
0x00020003 (SORRY,HIGH) = Could not grab drive
0x00020004 (NOTE,HIGH) = Opened O_EXCL scsi sibling
0x00020005 (FATAL,HIGH) = Failed to open device
0x00020005 (SORRY,HIGH) = Failed to open device
0x00020006 (FATAL,HIGH) = Too many scsi siblings
0x00020007 (NOTE,HIGH) = Closed O_EXCL scsi siblings
0x00020008 (SORRY,HIGH) = Device busy. Failed to fcntl-lock
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
From the hunt on Assert:
General library operations:
0x00020101 (WARNING,HIGH) = Cannot find given worker item
0x00020102 (SORRY,HIGH) = A drive operation is still going on
@ -311,7 +443,7 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
0x00020104 (SORRY,HIGH) = NULL pointer caught
0x00020105 (SORRY,HIGH) = Drive is already released
0x00020106 (SORRY,HIGH) = Drive is busy on attempt to close
0x00020107 (SORRY,HIGH) = Drive is busy on attempt to shut down library
0x00020107 (WARNING,HIGH) = A drive is still busy on shutdown of library
0x00020108 (SORRY,HIGH) = Drive is not grabbed on disc status inquiry
0x00020108 (FATAL,HIGH) = Could not allocate new drive object
0x00020109 (FATAL,HIGH) = Library not running
@ -320,7 +452,7 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
0x0002010c (FATAL,HIGH) = Failed to transfer command to drive
0x0002010d (DEBUG,HIGH) = Could not inquire TOC
0x0002010e (FATAL,HIGH) = Attempt to read ATIP from ungrabbed drive
0x0002010f
0x0002010f (DEBUG,HIGH) = SCSI error condition on command
0x00020110 (FATAL,HIGH) = Persistent drive address too long
0x00020111 (FATAL,HIGH) = Could not allocate new auxiliary object
0x00020112 (SORRY,HIGH) = Bad combination of write_type and block_type
@ -329,12 +461,202 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
0x00020115 (SORRY,HIGH) = Attempt to set track mode to unusable value
0x00020116 (FATAL,HIGH) = Track mode has unusable value
0x00020117 (FATAL,HIGH) = toc_entry of drive is already in use
0x00020118 (DEBUG,HIGH) = Closing track
0x00020119 (DEBUG,HIGH) = Closing session
0x0002011a (NOTE,HIGH) = Padding up track to minimum size
0x0002011b (FATAL,HIGH) = Attempt to read track info from ungrabbed drive
0x0002011c (FATAL,HIGH) = Attempt to read track info from busy drive
0x0002011d (FATAL,HIGH) = SCSI error on write
0x0002011e (SORRY,HIGH) = Unsuitable media detected
0x0002011f (SORRY,HIGH) = Burning is restricted to a single track
0x00020120 (NOTE,HIGH) = FORMAT UNIT ignored
0x00020121 (FATAL,HIGH) = Write preparation setup failed
0x00020122 (FATAL,HIGH) = SCSI error on format_unit
0x00020123 (SORRY,HIGH) = DVD Media are unsuitable for desired track type
0x00020124 (SORRY,HIGH) = SCSI error on set_streaming
0x00020125 (SORRY,HIGH) = Write start address not supported
0x00020126 (SORRY,HIGH) = Write start address not properly aligned
0x00020127 (NOTE,HIGH) = Write start address is ...
0x00020128 (FATAL,HIGH) = Unsupported inquiry_type with mmc_get_performance
0x00020129 (SORRY,HIGH) = Will not format media type
0x0002012a (FATAL,HIGH) = Cannot inquire write mode capabilities
0x0002012b (FATAL,HIGH) = Drive offers no suitable write mode with this job
0x0002012c (SORRY,HIGH) = Too many logical tracks recorded
0x0002012d (FATAL,HIGH) = Exceeding range of permissible write addresses
0x0002012e (NOTE,HIGH) = Activated track default size
0x0002012f (SORRY,HIGH) = SAO is restricted to single fixed size session
0x00020130 (SORRY,HIGH) = Drive and media state unsuitable for blanking
0x00020131 (SORRY,HIGH) = No suitable formatting type offered by drive
0x00020132 (SORRY,HIGH) = Selected format is not suitable for libburn
0x00020133 (SORRY,HIGH) = Cannot mix data and audio in SAO mode
0x00020134 (NOTE,HIGH) = Defaulted TAO to DAO
0x00020135 (SORRY,HIGH) = Cannot perform TAO, job unsuitable for DAO
0x00020136 (SORRY,HIGH) = DAO burning restricted to single fixed size track
0x00020137 (HINT,HIGH) = TAO would be possible
0x00020138 (FATAL,HIGH) = Cannot reserve track
0x00020139 (SORRY,HIGH) = Write job parameters are unsuitable
0x0002013a (FATAL,HIGH) = No suitable media detected
0x0002013b (DEBUG,HIGH) = SCSI command indicates host or driver error
0x0002013c (SORRY,HIGH) = Malformed capabilities page 2Ah received
0x0002013d (DEBUG,LOW) = Waiting for free buffer space takes long time
0x0002013e (SORRY,HIGH) = Timeout with waiting for free buffer. Now disabled
0x0002013f (DEBUG,LOW) = Reporting total time spent with waiting for buffer
0x00020140 (FATAL,HIGH) = Drive is busy on attempt to write random access
0x00020141 (SORRY,HIGH) = Write data count not properly aligned
0x00020142 (FATAL,HIGH) = Drive is not grabbed on random access write
0x00020143 (SORRY,HIGH) = Read start address not properly aligned
0x00020144 (SORRY,HIGH) = SCSI error on read
0x00020145 (FATAL,HIGH) = Drive is busy on attempt to read data
0x00020146 (FATAL,HIGH) = Drive is a virtual placeholder
0x00020147 (SORRY,HIGH) = Cannot address start byte
0x00020148 (SORRY,HIGH) = Cannot write desired amount of data
0x00020149 (SORRY,HIGH) = Unsuitable filetype for pseudo-drive
0x0002014a (SORRY,HIGH) = Cannot read desired amount of data
0x0002014b (SORRY,HIGH) = Drive is already registered resp. scanned
0x0002014c (FATAL,HIGH) = Emulated drive caught in SCSI function
0x0002014d (SORRY,HIGH) = Asynchromous SCSI error
0x0002014f (SORRY,HIGH) = Timeout with asynchromous SCSI command
0x00020150 (DEBUG,LOW) = Reporting asynchronous waiting time
0x00020151 (FATAL,HIGH) = Read attempt on write-only drive
0x00020152 (FATAL,HIGH) = Cannot start fifo thread
0x00020153 (SORRY,HIGH) = Read error on fifo input
0x00020154 (NOTE,HIGH) = Forwarded input error ends output
0x00020155 (SORRY,HIGH) = Desired fifo buffer too large
0x00020156 (SORRY,HIGH) = Desired fifo buffer too small
0x00020157 (FATAL,HIGH) = burn_source is not a fifo object
0x00020158 (DEBUG,LOW) = Reporting thread disposal precautions
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
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
libdax_audioxtr:
0x00020200 (SORRY,HIGH) = Cannot open audio source file
0x00020201 (SORRY,HIGH) = Audio source file has unsuitable format
0x00020202 (SORRY,HIGH) = Failed to prepare reading of audio data
------------------------------------------------------------------------------
Range "vreixo" : 0x00030000 to 0x0003ffff
0x0003ffff (FAILURE,HIGH) = Operation canceled
0x0003fffe (FATAL,HIGH) = Unknown or unexpected fatal error
0x0003fffd (FAILURE,HIGH) = Unknown or unexpected error
0x0003fffc (FATAL,HIGH) = Internal programming error
0x0003fffb (FAILURE,HIGH) = NULL pointer where NULL not allowed
0x0003fffa (FATAL,HIGH) = Memory allocation error
0x0003fff9 (FATAL,HIGH) = Interrupted by a signal
0x0003fff8 (FAILURE,HIGH) = Invalid parameter value
0x0003fff7 (FATAL,HIGH) = Cannot create a needed thread
0x0003fff6 (FAILURE,HIGH) = Write error
0x0003fff5 (FAILURE,HIGH) = Buffer read error
0x0003ffc0 (FAILURE,HIGH) = Trying to add a node already added to another dir
0x0003ffbf (FAILURE,HIGH) = Node with same name already exist
0x0003ffbe (FAILURE,HIGH) = Trying to remove a node that was not added to dir
0x0003ffbd (FAILURE,HIGH) = A requested node does not exist
0x0003ffbc (FAILURE,HIGH) = Image already bootable
0x0003ffbb (FAILURE,HIGH) = Trying to use an invalid file as boot image
0x0003ff80 (FAILURE,HIGH) = Error on file operation
0x0003ff7f (FAILURE,HIGH) = Trying to open an already openned file
0x0003ff7e (FAILURE,HIGH) = Access to file is not allowed
0x0003ff7d (FAILURE,HIGH) = Incorrect path to file
0x0003ff7c (FAILURE,HIGH) = The file does not exist in the filesystem
0x0003ff7b (FAILURE,HIGH) = Trying to read or close a file not openned
0x0003ff7a (FAILURE,HIGH) = Directory used where no dir is expected
0x0003ff79 (FAILURE,HIGH) = File read error
0x0003ff78 (FAILURE,HIGH) = Not dir used where a dir is expected
0x0003ff77 (FAILURE,HIGH) = Not symlink used where a symlink is expected
0x0003ff76 (FAILURE,HIGH) = Cannot seek to specified location
0x0003ff75 (HINT,MEDIUM) = File not supported in ECMA-119 tree and ignored
0x0003ff74 (HINT,MEDIUM) = File bigger than supported by used standard
0x0003ff73 (MISHAP,HIGH) = File read error during image creation
0x0003ff72 (HINT,MEDIUM) = Cannot convert filename to requested charset
0x0003ff71 (SORRY,HIGH) = File cannot be added to the tree
0x0003ff70 (HINT,MEDIUM) = File path breaks specification constraints
0x0003ff00 (FAILURE,HIGH) = Charset conversion error
0x0003feff (FAILURE,HIGH) = Too much files to mangle
0x0003fec0 (FAILURE,HIGH) = Wrong or damaged Primary Volume Descriptor
0x0003febf (SORRY,HIGH) = Wrong or damaged RR entry
0x0003febe (SORRY,HIGH) = Unsupported RR feature
0x0003febd (FAILURE,HIGH) = Wrong or damaged ECMA-119
0x0003febc (FAILURE,HIGH) = Unsupported ECMA-119 feature
0x0003febb (SORRY,HIGH) = Wrong or damaged El-Torito catalog
0x0003feba (SORRY,HIGH) = Unsupported El-Torito feature
0x0003feb9 (SORRY,HIGH) = Cannot patch isolinux boot image
0x0003feb8 (SORRY,HIGH) = Unsupported SUSP feature
0x0003feb7 (WARNING,HIGH) = Error on a RR entry that can be ignored
0x0003feb6 (HINT,MEDIUM) = Error on a RR entry that can be ignored
0x0003feb5 (WARNING,HIGH) = Multiple ER SUSP entries found
0x0003feb4 (HINT,MEDIUM) = Unsupported volume descriptor found
0x0003feb3 (WARNING,HIGH) = El-Torito related warning
0x0003feb2 (MISHAP,HIGH) = Image write cancelled
0x0003feb1 (WARNING,HIGH) = El-Torito image is hidden
Outdated codes which may not be re-used for other purposes than
re-instating them, if ever:
X 0x00031001 (SORRY,HIGH) = Cannot read file (ignored)
X 0x00031002 (FATAL,HIGH) = Cannot read file (operation canceled)
X 0x00031000 (FATAL,HIGH) = Unsupported ISO-9660 image
X 0x00031001 (HINT,MEDIUM) = Unsupported Vol Desc that will be ignored
X 0x00031002 (FATAL,HIGH) = Damaged ISO-9660 image
X 0x00031003 (SORRY,HIGH) = Cannot read previous image file
X 0x00030101 (HINT,MEDIUM) = Unsupported SUSP entry that will be ignored
X 0x00030102 (SORRY,HIGH) = Wrong/damaged SUSP entry
X 0x00030103 (WARNING,MEDIUM)= Multiple SUSP ER entries where found
X 0x00030111 (SORRY,HIGH) = Unsupported RR feature
X 0x00030112 (SORRY,HIGH) = Error in a Rock Ridge entry
X 0x00030201 (HINT,MEDIUM) = Unsupported Boot Vol Desc that will be ignored
X 0x00030202 (SORRY,HIGH) = Wrong El-Torito catalog
X 0x00030203 (HINT,MEDIUM) = Unsupported El-Torito feature
X 0x00030204 (SORRY,HIGH) = Invalid file to be an El-Torito image
X 0x00030205 (WARNING,MEDIUM)= Cannot properly patch isolinux image
X 0x00030206 (WARNING,MEDIUM)= Copying El-Torito from a previous image without
X enought info about it
X 0x00030301 (NOTE,MEDIUM) = Unsupported file type for Joliet tree
------------------------------------------------------------------------------
Range "application" : 0x00040000 to 0x0004ffff
0x00040000 (ABORT,HIGH) : Application supplied message
0x00040001 (FATAL,HIGH) : Application supplied message
0x00040002 (SORRY,HIGH) : Application supplied message
0x00040003 (WARNING,HIGH) : Application supplied message
0x00040004 (HINT,HIGH) : Application supplied message
0x00040005 (NOTE,HIGH) : Application supplied message
0x00040006 (UPDATE,HIGH) : Application supplied message
0x00040007 (DEBUG,HIGH) : Application supplied message
0x00040008 (*,HIGH) : Application supplied message
------------------------------------------------------------------------------
Range "libisofs-xorriso" : 0x00050000 to 0x0005ffff
This is an alternative representation of libisofs.so.6 error codes in xorriso.
If values returned by iso_error_get_code() do not fit into 0x30000 to 0x3ffff
then they get truncated to 16 bit and mapped into this range.
(This should never need to happen, of course.)
------------------------------------------------------------------------------
Range "libisoburn" : 0x00060000 to 0x00006ffff
0x00060000 (*,*) : Message which shall be attributed to libisoburn
>>> the messages of libisoburn need to be registered individually
------------------------------------------------------------------------------

View File

@ -0,0 +1,37 @@
#!/bin/sh
# libdax_msgs_to_iso_msgs.sh
# generates ${xyz}_msgs.[ch] from libdax_msgs.[ch]
# To be executed within ./libburn-* resp ./cdrskin-*
# The module name for the generated sourcecode in several
# uppercase-lowercase forms
xyz="libiso"
Xyz="Libiso"
XYZ="LIBISO"
# The project name for which the generated code shall serve
project="libisofs"
for i in libburn/libdax_msgs.[ch]
do
target_adr=$(echo "$i" | sed -e "s/libdax_/${xyz}_/")
echo "$target_adr"
sed \
-e "s/^\/\* libdax_msgs/\/* ${xyz}_msgs (generated from XYZ_msgs : $(date))/" \
-e "s/Message handling facility of libdax/Message handling facility of ${project}/" \
-e "s/libdax_/${xyz}_/g" \
-e "s/libdax:/${xyz}:/g" \
-e "s/Libdax_/${Xyz}_/g" \
-e "s/LIBDAX_/${XYZ}_/g" \
-e "s/generated from XYZ_msgs/generated from libdax_msgs/" \
-e "s/${xyz}_msgs is designed to serve in libraries/libdax_msgs is designed to serve in libraries/" \
-e "s/Owner of ${xyz}_msgs is libburn/Owner of libdax_msgs is libburn/" \
\
<"$i" >"$target_adr"
done

File diff suppressed because it is too large Load Diff

View File

@ -37,7 +37,11 @@ void mmc_set_speed(struct burn_drive *, int, int);
void mmc_read_lead_in(struct burn_drive *, struct buffer *);
void mmc_perform_opc(struct burn_drive *);
void mmc_get_configuration(struct burn_drive *);
int mmc_get_nwa(struct burn_drive *);
/* ts A61110 : added parameters trackno, lba, nwa. Redefined return value.
@return 1=nwa is valid , 0=nwa is not valid , -1=error */
int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa);
void mmc_send_cue_sheet(struct burn_drive *, struct cue_sheet *);
/* ts A61023 : get size and free space of drive buffer */
@ -47,4 +51,32 @@ int mmc_read_buffer_capacity(struct burn_drive *d);
*/
int mmc_setup_drive(struct burn_drive *d);
/* ts A61219 : learned much from dvd+rw-tools-7.0: plus_rw_format()
and mmc5r03c.pdf, 6.5 FORMAT UNIT */
int mmc_format_unit(struct burn_drive *d, off_t size, int flag);
/* ts A61225 : obtain write speed descriptors via ACh GET PERFORMANCE */
int mmc_get_write_performance(struct burn_drive *d);
/* ts A61229 : outsourced from spc_select_write_params() */
/* Note: Page data is not zeroed here to allow preset defaults. Thus
memset(pd, 0, 2 + d->mdata->write_page_length);
is the eventual duty of the caller.
*/
int mmc_compose_mode_page_5(struct burn_drive *d,
const struct burn_write_opts *o,
unsigned char *pd);
/* 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);
/* mmc5r03c.pdf 4.3.4.4.1 d) "The maximum number of RZones is 2 302." */
#define BURN_MMC_FAKE_TOC_MAX_SIZE 2302
#endif /*__MMC*/

View File

@ -21,6 +21,10 @@ struct burn_source *burn_null_source_new(void)
src->read_sub = NULL;
src->get_size = 0;
/* ts A70126 */
src->set_size = NULL;
src->free_data = NULL;
src->data = NULL;
return src;

View File

@ -1,5 +1,6 @@
#include "libburn.h"
#include "options.h"
#include "drive.h"
#include "transport.h"
/* ts A61007 */
@ -32,6 +33,12 @@ struct burn_write_opts *burn_write_opts_new(struct burn_drive *drive)
opts->simulate = 0;
opts->underrun_proof = drive->mdata->underrun_proof;
opts->perform_opc = 1;
opts->obs = -1;
opts->obs_pad = 0;
opts->start_byte = -1;
opts->fill_up_media = 0;
opts->force_is_set = 0;
opts->do_stream_recording = 0;
opts->has_mediacatalog = 0;
opts->format = BURN_CDROM;
opts->multi = 0;
@ -118,16 +125,26 @@ void burn_write_opts_set_format(struct burn_write_opts *opts, int format)
int burn_write_opts_set_simulate(struct burn_write_opts *opts, int sim)
{
/* <<< ts A70529 :
One cannot predict the ability to simulate from page 05h
information alone. This check is now done later in
function burn_write_opts_auto_write_type().
if (opts->drive->mdata->simulate) {
opts->simulate = sim;
return 1;
}
return 0;
*/
opts->simulate = !!sim;
return 1;
}
int burn_write_opts_set_underrun_proof(struct burn_write_opts *opts,
int underrun_proof)
{
if (!opts->drive->mdata->valid)
return 0;
if (opts->drive->mdata->underrun_proof) {
opts->underrun_proof = underrun_proof;
return 1;
@ -152,6 +169,235 @@ void burn_write_opts_set_mediacatalog(struct burn_write_opts *opts,
memcpy(opts->mediacatalog, &mediacatalog, 13);
}
/* ts A61106 */
void burn_write_opts_set_multi(struct burn_write_opts *opts, int multi)
{
opts->multi = !!multi;
}
/* ts A61222 */
void burn_write_opts_set_start_byte(struct burn_write_opts *opts, off_t value)
{
opts->start_byte = value;
}
/* ts A70207 API */
/** @param flag Bitfield for control purposes:
bit0= do not choose type but check the one that is already set
bit1= do not issue error messages via burn_msgs queue
*/
enum burn_write_types burn_write_opts_auto_write_type(
struct burn_write_opts *opts, struct burn_disc *disc,
char reasons[BURN_REASONS_LEN], int flag)
{
struct burn_multi_caps *caps = NULL;
struct burn_drive *d = opts->drive;
struct burn_disc_mode_demands demands;
enum burn_write_types wt;
int ret, would_do_sao = 0;
char *reason_pt;
reasons[0] = 0;
if (d->status != BURN_DISC_BLANK &&
d->status != BURN_DISC_APPENDABLE){
if (d->status == BURN_DISC_FULL)
strcat(reasons, "MEDIA: closed or not recordable, ");
else
strcat(reasons,"MEDIA: no writeable media detected, ");
if (!(flag & 3))
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002013a,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"No suitable media detected", 0, 0);
return BURN_WRITE_NONE;
}
ret = burn_disc_get_write_mode_demands(disc, opts, &demands,
!!opts->fill_up_media);
if (ret <= 0) {
strcat(reasons, "cannot recognize job demands, ");
{wt = BURN_WRITE_NONE; goto ex;}
}
if (demands.exotic_track && !d->current_is_cd_profile) {
if (demands.audio)
strcat(reasons, "audio track prohibited by non-CD, ");
else
strcat(reasons, "exotic track prohibited by non-CD, ");
{wt = BURN_WRITE_NONE; goto ex;}
}
if ((flag & 1) && opts->write_type != BURN_WRITE_SAO)
goto try_tao;
reason_pt = reasons + strlen(reasons);
strcat(reasons, "SAO: ");
if (d->status != BURN_DISC_BLANK) {
strcat(reasons, "write type SAO works only on blank media, ");
goto try_tao;
}
burn_disc_free_multi_caps(&caps);
ret = burn_disc_get_multi_caps(d, BURN_WRITE_SAO, &caps, 0);
if (ret < 0) {
no_caps:;
strcat(reasons, "cannot inquire write mode capabilities, ");
{wt = BURN_WRITE_NONE; goto ex;}
} else if (ret == 0) {
strcat(reasons, "no SAO offered by drive and media, ");
goto no_sao;
}
if ((opts->multi || demands.multi_session) &&
!caps->multi_session)
strcat(reasons, "multi session capability lacking, ");
if (demands.will_append)
strcat(reasons, "appended session capability lacking, ");
if (demands.multi_track && !caps->multi_track)
strcat(reasons, "multi track capability lacking, ");
if (demands.unknown_track_size == 1 &&
(caps->might_do_sao == 1 || caps->might_do_sao == 3))
strcat(reasons, "track size unpredictable, ");
if (demands.mixed_mode)
strcat(reasons, "tracks of different modes mixed, ");
if (demands.exotic_track && !d->current_is_cd_profile)
strcat(reasons, "non-data track on non-cd, ");
else if (d->current_is_cd_profile)
if ((d->block_types[BURN_WRITE_TAO] & demands.block_types) !=
demands.block_types)
strcat(reasons, "drive dislikes block type, ");
if (d->current_is_cd_profile && opts->fill_up_media)
strcat(reasons, "cd sao cannot do media fill up yet, ");
if (strcmp(reason_pt, "SAO: ") != 0)
goto no_sao;
would_do_sao = 1;
if (demands.unknown_track_size == 2 && (!(flag & 1)) &&
(caps->might_do_sao == 1 || caps->might_do_sao == 3)) {
strcat(reasons, "would have to use default track sizes, ");
goto no_sao;
} else if (caps->might_do_sao >= 3 && !(flag & 1))
goto try_tao;
do_sao:;
if (caps->might_simulate == 0 && opts->simulate && !opts->force_is_set)
goto no_simulate;
if (!(flag & 1))
burn_write_opts_set_write_type(
opts, BURN_WRITE_SAO, BURN_BLOCK_SAO);
{wt = BURN_WRITE_SAO; goto ex;}
no_sao:;
try_tao:;
if ((flag & 1) && opts->write_type != BURN_WRITE_TAO)
goto try_raw;
reason_pt = reasons + strlen(reasons);
strcat(reasons, "TAO: ");
burn_disc_free_multi_caps(&caps);
ret = burn_disc_get_multi_caps(d, BURN_WRITE_TAO, &caps, 0);
if (ret < 0)
goto no_caps;
if (ret == 0) {
strcat(reasons, "no TAO offered by drive and media, ");
goto no_tao;
}
if ((opts->multi || demands.multi_session) && !caps->multi_session)
strcat(reasons, "multi session capability lacking, ");
if (demands.multi_track && !caps->multi_track)
strcat(reasons, "multi track capability lacking, ");
if (demands.exotic_track && !d->current_is_cd_profile)
strcat(reasons, "non-data track on non-cd, ");
if (d->current_is_cd_profile && !opts->force_is_set)
if ((d->block_types[BURN_WRITE_TAO] & demands.block_types) !=
demands.block_types)
strcat(reasons, "drive dislikes block type, ");
if (strcmp(reason_pt, "TAO: ") != 0)
goto no_tao;
/* ( TAO data/audio block size will be handled automatically ) */
if (caps->might_simulate == 0 && opts->simulate && !opts->force_is_set)
goto no_simulate;
if (!(flag & 1))
burn_write_opts_set_write_type(
opts, BURN_WRITE_TAO, BURN_BLOCK_MODE1);
{wt = BURN_WRITE_TAO; goto ex;}
no_tao:;
if (would_do_sao && !(flag & 1))
goto do_sao;
if (!d->current_is_cd_profile)
goto no_write_mode;
try_raw:;
if ((flag & 1) && opts->write_type != BURN_WRITE_RAW)
goto no_write_mode;
if (!(flag & 1)) /* For now: no automatic raw write modes */
goto no_write_mode;
reason_pt = reasons + strlen(reasons);
strcat(reasons, "RAW: ");
if (!d->current_is_cd_profile)
strcat(reasons, "write type RAW prohibited by non-cd, ");
else if (d->status != BURN_DISC_BLANK)
strcat(reasons, "write type RAW works only on blank media, ");
else if ((d->block_types[BURN_WRITE_TAO] & demands.block_types) !=
demands.block_types)
strcat(reasons, "drive dislikes block type, ");
if (strcmp(reason_pt, "RAW: ") != 0)
goto no_write_mode;
if (!opts->force_is_set)
goto no_simulate;
/* For now: no setting of raw write modes */
{wt = BURN_WRITE_RAW; goto ex;}
no_write_mode:;
{wt = BURN_WRITE_NONE; goto ex;}
no_simulate:;
strcat(reasons,
"simulation of write job not supported by drive and media, ");
{wt = BURN_WRITE_NONE; goto ex;}
ex:;
burn_disc_free_multi_caps(&caps);
if (wt == BURN_WRITE_NONE && !(flag & 3)) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002012b,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Drive offers no suitable write mode with this job",
0, 0);
}
return wt;
}
/* ts A70213 : new API function */
void burn_write_opts_set_fillup(struct burn_write_opts *opts,int fill_up_media)
{
opts->fill_up_media = !!fill_up_media;
return;
}
/* ts A70303: API */
void burn_write_opts_set_force(struct burn_write_opts *opts, int use_force)
{
opts->force_is_set = !!use_force;
}
/* ts A80412: API */
void burn_write_opts_set_stream_recording(struct burn_write_opts *opts,
int value)
{
opts->do_stream_recording = !!value;
}
/* ts A70901: API */
struct burn_drive *burn_write_opts_get_drive(struct burn_write_opts *opts)
{
return opts->drive;
}
void burn_read_opts_set_raw(struct burn_read_opts *opts, int raw)
{
opts->raw = raw;
@ -198,3 +444,4 @@ void burn_read_opts_set_hardware_error_retries(struct burn_read_opts *opts,
{
opts->hardware_error_retries = hardware_error_retries;
}

View File

@ -32,6 +32,28 @@ struct burn_write_opts
/** Perform calibration of the drive's laser before beginning the
write. */
unsigned int perform_opc:1;
/* ts A61219 : Output block size to trigger buffer flush if hit.
-1 with CD, 32 kB with DVD */
int obs;
int obs_pad; /* 1=pad up last block to obs */
/* ts A61222 : Start address for media which allow a choice */
off_t start_byte;
/* ts A70213 : Wether to fill up the available space on media */
int fill_up_media;
/* ts A70303 : Wether to override conformance checks:
- the check wether CD write+block type is supported by the drive
*/
int force_is_set;
/* 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 */
int do_stream_recording;
/** A disc can have a media catalog number */
int has_mediacatalog;
unsigned char mediacatalog[13];

61
libburn/os-freebsd.h Normal file
View File

@ -0,0 +1,61 @@
/* os-freebsd.h
Operating system specific libburn definitions and declarations. Included
by os.h in case of compilation for
FreeBSD with CAM
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
*/
/** 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, \
SIGBUS, SIGPROF, SIGSYS, SIGTRAP, \
SIGVTALRM, SIGXCPU, SIGXFSZ
/* 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", \
"SIGBUS", "SIGPROF", "SIGSYS", "SIGTRAP", \
"SIGVTALRM", "SIGXCPU", "SIGXFSZ"
/* The number of above list items */
#define BURN_OS_SIGNAL_COUNT 23
/** 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 ! */
#define BURN_OS_TRANSPORT_BUFFER_SIZE 32768
/** To hold all state information of BSD device enumeration
which are now local in sg_enumerate() . So that sg_give_next_adr()
can work in BSD and sg_enumerate() can use it.
*/
#define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \
struct burn_drive_enumeration_state; \
typedef struct burn_drive_enumeration_state *burn_drive_enumerator_t;
/* The list of operating system dependent elements in struct burn_drive.
To be initialized and used within sg-*.c .
*/
#define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \
struct cam_device* cam;

82
libburn/os-linux.h Normal file
View File

@ -0,0 +1,82 @@
/* 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)
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
*/
/** 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, \
SIGBUS, SIGPOLL, SIGPROF, SIGSYS, SIGTRAP, \
SIGVTALRM, SIGXCPU, SIGXFSZ
/* 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", \
"SIGBUS", "SIGPOLL", "SIGPROF", "SIGSYS", "SIGTRAP", \
"SIGVTALRM", "SIGXCPU", "SIGXFSZ"
/* The number of above list items */
#define BURN_OS_SIGNAL_COUNT 24
/** 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 ! */
/* ts A70523 : >32k seems not good with kernel 2.4 USB drivers and audio
#define BURN_OS_TRANSPORT_BUFFER_SIZE 32768
*/
/* ts A80414 : curbed in write.c CD media to Libburn_cd_obS = 32 kiB
re-enlarged transport to 64 kiB for BD-RE experiments
*/
#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;
/* Parameters for sibling list. See sibling_fds, sibling_fnames */
#define BURN_OS_SG_MAX_SIBLINGS 5
#define BURN_OS_SG_MAX_NAMELEN 16
/* The list of operating system dependent elements in struct burn_drive.
Usually they are initialized in sg-*.c:enumerate_common().
*/
#define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \
int fd; \
\
/* ts A60926 : trying to lock against growisofs /dev/srN, /dev/scdN */ \
int sibling_count; \
int sibling_fds[BURN_OS_SG_MAX_SIBLINGS]; \
/* ts A70409 : DDLP */ \
char sibling_fnames[BURN_OS_SG_MAX_SIBLINGS][BURN_OS_SG_MAX_NAMELEN];

34
libburn/os.h Normal file
View File

@ -0,0 +1,34 @@
/* os.h
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
*/
#ifndef BURN_OS_H_INCLUDED
#define BURN_OS_H_INCLUDED 1
/*
Operating system case distinction
*/
#ifdef __FreeBSD__
/* ----------------------------- FreeBSD with CAM -------------------------- */
#include "os-freebsd.h"
#else /* operating system case distinction */
/* --------- Linux kernels 2.4 and 2.6 with Linux SCSI Generic (sg) -------- */
#include "os-linux.h"
#endif /* End of operating system case distinction */
#endif /* ! BURN_OS_H_INCLUDED */

View File

@ -12,6 +12,9 @@
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <fcntl.h>
#include <errno.h>
#include "sector.h"
#include "libburn.h"
#include "drive.h"
@ -31,6 +34,12 @@
#include "read.h"
#include "options.h"
/* ts A70812 */
#include "error.h"
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
void burn_disc_read(struct burn_drive *d, const struct burn_read_opts *o)
{
#if 0
@ -280,3 +289,203 @@ static void flipq(unsigned char *sub)
*(sub + 12 + 11) = ~*(sub + 12 + 11);
}
*/
/* ts A70904 */
/** @param flag bit0=be silent on data shortage */
int burn_stdio_read(int fd, char *buf, int bufsize, struct burn_drive *d,
int flag)
{
int todo, count = 0;
for(todo = bufsize; todo > 0; ) {
count = read(fd, buf + (bufsize - todo), todo);
if(count <= 0)
break;
todo -= count;
}
if(todo > 0 && !(flag & 1)) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002014a,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Cannot read desired amount of data", errno, 0);
}
if (count < 0)
return -1;
return (bufsize - todo);
}
/* ts A70812 : API function */
int burn_read_data(struct burn_drive *d, off_t byte_address,
char data[], off_t data_size, off_t *data_count, int flag)
{
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, *buffer_mem = d->buffer;
/*
#define Libburn_read_data_adr_logginG 1
*/
#ifdef Libburn_read_data_adr_logginG
static FILE *log_fp= NULL;
if(log_fp == NULL)
log_fp = fopen("/tmp/burn_read_data_log", "a");
if(log_fp!=NULL)
fprintf(log_fp, "%d\n", (int) (byte_address / 2048));
#endif /* Libburn_read_data_logginG */
*data_count = 0;
sose_mem = d->silent_on_scsi_error;
if (d->released) {
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x00020142,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Drive is not grabbed on random access read", 0, 0);
return 0;
}
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);
return 0;
} else if (d->drive_role == 3) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020151,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Read attempt on write-only drive", 0, 0);
return 0;
}
if ((byte_address % alignment) != 0) {
sprintf(msg,
"Read start address not properly aligned (%d bytes)",
alignment);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020143,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
return 0;
}
if (d->busy != BURN_DRIVE_IDLE) {
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x00020145,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Drive is busy on attempt to read data", 0, 0);
return 0;
}
if (d->drive_role != 1) {
/* <<< We need _LARGEFILE64_SOURCE defined by the build system.
*/
#ifndef O_LARGEFILE
#define O_LARGEFILE 0
#endif
fd = d->stdio_fd;
if (fd < 0)
d->stdio_fd = fd =
open(d->devname, O_RDONLY | O_LARGEFILE);
if (fd == -1) {
if (errno != ENOENT || !(flag & 2))
libdax_msgs_submit(libdax_messenger,
d->global_index,
0x00020005,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Failed to open device (a pseudo-drive) for reading",
errno, 0);
ret = 0; goto ex;
}
if (lseek(fd, byte_address, SEEK_SET) == -1) {
if (!(flag & 2))
libdax_msgs_submit(libdax_messenger,
d->global_index,
0x00020147,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Cannot address start byte", errno, 0);
ret = 0; goto ex;
}
}
d->busy = BURN_DRIVE_READING_SYNC;
d->buffer = &buf;
start = byte_address / 2048;
upto = start + data_size / 2048;
if (data_size % 2048)
upto++;
wpt = data;
for (; start < upto; start += chunksize) {
chunksize = upto - start;
if (chunksize > 16) {
chunksize = 16;
cpy_size = 16 * 2048;
} else
cpy_size = data_size - *data_count;
if (flag & 2)
d->silent_on_scsi_error = 1;
if (d->drive_role == 1) {
err = d->read_10(d, start, chunksize, d->buffer);
} else {
ret = burn_stdio_read(fd, (char *) d->buffer->data,
cpy_size, d, !!(flag & 2));
err = 0;
if (ret <= 0)
err = BE_CANCELLED;
}
if (flag & 2)
d->silent_on_scsi_error = sose_mem;
if (err == BE_CANCELLED) {
/* Try to read a smaller part of the chunk */
if(!(flag & 4))
for (i = 0; i < chunksize - 1; i++) {
if (flag & 2)
d->silent_on_scsi_error = 1;
if (d->drive_role == 1) {
err = d->read_10(d, start + i, 1,
d->buffer);
} else {
ret = burn_stdio_read(fd,
(char *) d->buffer->data,
2048, d, 1);
if (ret <= 0)
err = BE_CANCELLED;
}
if (flag & 2)
d->silent_on_scsi_error = sose_mem;
if (err == BE_CANCELLED)
break;
memcpy(wpt, d->buffer->data, 2048);
wpt += 2048;
*data_count += 2048;
}
if (!(flag & 2))
libdax_msgs_submit(libdax_messenger,
d->global_index,
0x00020000,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
"burn_read_data() returns 0",
0, 0);
ret = 0; goto ex;
}
memcpy(wpt, d->buffer->data, cpy_size);
wpt += cpy_size;
*data_count += cpy_size;
}
ret = 1;
ex:;
/* <<< let it open until drive is given up or writing shall happen
if (fd != -1)
close(fd);
*/
d->buffer = buffer_mem;
d->busy = BURN_DRIVE_IDLE;
return ret;
}

View File

@ -3,46 +3,112 @@
/* scsi block commands */
#include <string.h>
#include <unistd.h>
#include "transport.h"
#include "sbc.h"
#include "spc.h"
#include "options.h"
/* ts A70910
debug: for tracing calls which might use open drive fds
or for catching SCSI usage of emulated drives. */
int mmc_function_spy(struct burn_drive *d, char * text);
/* spc command set */
static char SBC_LOAD[] = { 0x1b, 0, 0, 0, 3, 0 };
static char SBC_UNLOAD[] = { 0x1b, 0, 0, 0, 2, 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 };
void sbc_load(struct burn_drive *d)
{
struct command c;
if (mmc_function_spy(d, "load") <= 0)
return;
scsi_init_command(&c, SBC_LOAD, sizeof(SBC_LOAD));
/*
memcpy(c.opcode, SBC_LOAD, sizeof(SBC_LOAD));
c.retry = 1;
c.oplen = sizeof(SBC_LOAD);
c.dir = NO_TRANSFER;
c.page = NULL;
*/
c.retry = 1;
/* ts A70921 : Had to revoke Immed because of LG GSA-4082B */
/* c.opcode[1] |= 1; / * ts A70918 : Immed */
c.dir = NO_TRANSFER;
d->issue_command(d, &c);
if (c.error)
return;
/* ts A70923 : Needed regardless of Immed bit. Was once 1 minute, now
5 minutes for loading. If this does not suffice then other commands
shall fail righteously. */
spc_wait_unit_attention(d, 300, "waiting after START UNIT (+ LOAD)",0);
}
void sbc_eject(struct burn_drive *d)
{
struct command c;
c.page = NULL;
if (mmc_function_spy(d, "eject") <= 0)
return;
scsi_init_command(&c, SBC_UNLOAD, sizeof(SBC_UNLOAD));
/*
memcpy(c.opcode, SBC_UNLOAD, sizeof(SBC_UNLOAD));
c.oplen = 1;
c.oplen = sizeof(SBC_UNLOAD);
c.page = NULL;
*/
c.opcode[1] |= 1; /* ts A70918 : Immed */
c.page = NULL;
c.dir = NO_TRANSFER;
d->issue_command(d, &c);
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)
{
struct command c;
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.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);
}
/* ts A61021 : the sbc specific part of sg.c:enumerate_common()
*/
int sbc_setup_drive(struct burn_drive *d)
{
d->eject = sbc_eject;
d->load = sbc_load;
d->start_unit = sbc_start_unit;
return 1;
}

View File

@ -8,6 +8,9 @@ struct burn_drive;
void sbc_load(struct burn_drive *);
void sbc_eject(struct burn_drive *);
/* ts A61118 */
int sbc_start_unit(struct burn_drive *);
/* ts A61021 : the sbc specific part of sg.c:enumerate_common()
*/
int sbc_setup_drive(struct burn_drive *d);

View File

@ -19,6 +19,15 @@
#include "toc.h"
#include "write.h"
#ifdef Libburn_log_in_and_out_streaM
/* <<< ts A61031 */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#endif /* Libburn_log_in_and_out_streaM */
/*static unsigned char isrc[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";*/
#define sector_common(X) d->alba++; d->rlba X;
@ -44,7 +53,8 @@ static void uncook_subs(unsigned char *dest, unsigned char *source)
int sector_get_outmode(enum burn_write_types write_type,
enum burn_block_types block_type)
{
if (write_type == BURN_WRITE_SAO)
/* ts A61103 : extended SAO condition to TAO */
if (write_type == BURN_WRITE_SAO || write_type == BURN_WRITE_TAO)
return 0;
else
switch (block_type) {
@ -81,6 +91,15 @@ 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 */
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 */
/* no track pointer means we're just generating 0s */
if (!track) {
memset(data, 0, count);
@ -104,13 +123,26 @@ static void get_bytes(struct burn_track *track, int count, unsigned char *data)
/* Next we use source data */
curr = valid;
if (!track->eos) {
valid = track->source->read(track->source, data + curr, count - curr);
if (track->source->read != NULL)
valid = track->source->read(track->source,
data + curr, count - curr);
else
valid = track->source->read_xt(track->source,
data + curr, count - curr);
} else valid = 0;
if (valid == -1) {
if (valid <= 0) { /* ts A61031 : extended from (valid == -1) */
track->eos = 1;
valid = 0;
}
track->sourcecount += valid;
#ifdef Libburn_log_in_and_out_streaM
/* <<< ts A61031 */
if(tee_fd!=-1 && valid>0) {
write(tee_fd, data + curr, valid);
}
#endif /* Libburn_log_in_and_out_streaM */
curr += valid;
shortage = count - curr;
@ -134,6 +166,12 @@ static void get_bytes(struct burn_track *track, int count, unsigned char *data)
if (!shortage)
goto ex;
/* ts A61031 */
if (shortage >= count)
track->track_data_done = 1;
if (track->open_ended)
goto ex;
/* If we're still short, and there's a "next" pointer, we pull from that.
if that depletes, we'll just fill with 0s.
*/
@ -152,15 +190,6 @@ ex:;
if(shortage)
memset(data + curr, 0, shortage); /* this is old icculus.org */
if (track->swap_source_bytes == 1) {
/*
{ static int swapping_count= 0;
fprintf(stderr,"\rlibburn_debug: swapping #%d \r",
swapping_count);
swapping_count++;
}
*/
for (i = 1; i < count; i += 2) {
tr = data[i];
data[i] = data[i-1];
@ -171,7 +200,9 @@ ex:;
/* ts A61009 : seems to hand out sector start pointer in opts->drive->buffer
and to count hand outs as well as reserved bytes */
static unsigned char *get_sector(struct burn_write_opts *opts, int inmode)
/* ts A61101 : added parameter track for counting written bytes */
static unsigned char *get_sector(struct burn_write_opts *opts,
struct burn_track *track, int inmode)
{
struct burn_drive *d = opts->drive;
struct buffer *out = d->buffer;
@ -191,11 +222,22 @@ static unsigned char *get_sector(struct burn_write_opts *opts, int inmode)
return NULL;
seclen += burn_subcode_length(outmode);
if (out->bytes + (seclen) >= BUFFER_SIZE) {
/* ts A61219 : opts->obs is eventually a 32k trigger for DVD */
if (out->bytes + seclen > BUFFER_SIZE ||
(opts->obs > 0 && out->bytes + seclen > opts->obs)) {
int err;
err = d->write(d, d->nwa, out);
if (err == BE_CANCELLED)
return NULL;
/* ts A61101 */
if(track != NULL) {
track->writecount += out->bytes;
track->written_sectors += out->sectors;
}
/* ts A61119 */
d->progress.buffered_bytes += out->bytes;
d->nwa += out->sectors;
out->bytes = 0;
out->sectors = 0;
@ -208,6 +250,32 @@ static unsigned char *get_sector(struct burn_write_opts *opts, int inmode)
return ret;
}
/* ts A61031 */
/* Revoke the counting of the most recent sector handed out by get_sector() */
static void unget_sector(struct burn_write_opts *opts, int inmode)
{
struct burn_drive *d = opts->drive;
struct buffer *out = d->buffer;
int outmode;
int seclen;
outmode = get_outmode(opts);
if (outmode == 0)
outmode = inmode;
/* ts A61009 : react on eventual failure of burn_sector_length()
(should not happen if API tested properly).
Ensures out->bytes >= out->sectors */
seclen = burn_sector_length(outmode);
if (seclen <= 0)
return;
seclen += burn_subcode_length(outmode);
out->bytes -= seclen;
out->sectors--;
}
/* either inmode == outmode, or outmode == raw. anything else is bad news */
/* ts A61010 : changed type to int in order to propagate said bad news */
/** @return 1 is ok, <= 0 is failure */
@ -289,6 +357,8 @@ static void convert_subs(struct burn_write_opts *o, int inmode,
out[0] = ~out[0];
out[1] = ~out[1];
break;
/* ts A61119 : to silence compiler warnings */
default:;
}
}
@ -335,7 +405,7 @@ int sector_toc(struct burn_write_opts *o, int mode)
unsigned char *data;
unsigned char subs[96];
data = get_sector(o, mode);
data = get_sector(o, NULL, mode);
if (data == NULL)
return 0;
/* ts A61010 */
@ -355,7 +425,7 @@ int sector_pregap(struct burn_write_opts *o,
unsigned char *data;
unsigned char subs[96];
data = get_sector(o, mode);
data = get_sector(o, NULL, mode);
if (data == NULL)
return 0;
/* ts A61010 */
@ -375,7 +445,7 @@ int sector_postgap(struct burn_write_opts *o,
unsigned char subs[96];
unsigned char *data;
data = get_sector(o, mode);
data = get_sector(o, NULL, mode);
if (data == NULL)
return 0;
/* ts A61010 */
@ -547,7 +617,7 @@ int sector_lout(struct burn_write_opts *o, unsigned char control, int mode)
unsigned char subs[96];
unsigned char *data;
data = get_sector(o, mode);
data = get_sector(o, NULL, mode);
if (!data)
return 0;
/* ts A61010 */
@ -566,14 +636,23 @@ int sector_data(struct burn_write_opts *o, struct burn_track *t, int psub)
unsigned char subs[96];
unsigned char *data;
data = get_sector(o, t->mode);
data = get_sector(o, t, t->mode);
if (!data)
return 0;
/* ts A61010 */
if (convert_data(o, t, t->mode, data) <= 0)
return 0;
if (!t->source->read_sub)
/* ts A61031 */
if (t->open_ended && t->track_data_done) {
unget_sector(o, t->mode);
return 2;
}
/* ts A61219 : allow track without .entry */
if (t->entry == NULL)
;
else if (!t->source->read_sub)
subcode_user(o, subs, t->entry->point,
t->entry->control, 1, &t->isrc, psub);
else if (!t->source->read_sub(t->source, subs, 96))
@ -622,6 +701,11 @@ int sector_headers_is_ok(struct burn_write_opts *o, int mode)
return 1;
if (o->write_type == BURN_WRITE_SAO)
return 1;
/* ts A61031 */
if (o->write_type == BURN_WRITE_TAO)
return 1;
if (mode & BURN_MODE1)
return 2;
return 0;
@ -650,6 +734,11 @@ void sector_headers(struct burn_write_opts *o, unsigned char *out,
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;
@ -736,7 +825,14 @@ void process_q(struct burn_drive *d, unsigned char *q)
#endif
/* this needs more info. subs in the data? control/adr? */
/* ts A61119 : One should not use inofficial compiler extensions.
>>> Some day this function needs to be implemented. At least for now
the result does not match the "mode" of cdrecord -toc.
*/
/*
#warning sector_identify needs to be written
*/
int sector_identify(unsigned char *data)
{
scramble(data);

631
libburn/sg-freebsd-port.c Normal file
View File

@ -0,0 +1,631 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/*
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: FreeBSD CAM (untested)
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_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_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_stdio_capacity() estimates the emulated media space of stdio-drives.
Porting hints are marked by the text "PORTING:".
Send feedback to libburn-hackers@pykix.org .
*/
/** PORTING : ------- OS dependent headers and definitions ------ */
#include <errno.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <string.h>
#include <sys/poll.h>
#include <camlib.h>
#include <cam/scsi/scsi_message.h>
#include <cam/scsi/scsi_pass.h>
#include <err.h> /* XXX */
/* ts A70909 */
#include <sys/statvfs.h>
/** PORTING : ------ libburn portable headers and definitions ----- */
#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;
/* is in portable part of libburn */
int burn_drive_is_banned(char *device_address);
/* ------------------------------------------------------------------------ */
/* ts A61115: Private functions. Port only if needed by public functions */
/* (Public functions are listed below) */
/* ------------------------------------------------------------------------ */
/* Helper function for scsi_give_next_adr() */
static int sg_init_enumerator(burn_drive_enumerator_t *idx)
{
idx->skip_device = 0;
if ((idx->fd = open(XPT_DEVICE, O_RDWR)) == -1) {
warn("couldn't open %s", XPT_DEVICE);
return -1;
}
bzero(&(idx->ccb), sizeof(union ccb));
idx->ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
idx->ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
idx->ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
idx->ccb.ccb_h.func_code = XPT_DEV_MATCH;
idx->bufsize = sizeof(struct dev_match_result) * 100;
idx->ccb.cdm.match_buf_len = idx->bufsize;
idx->ccb.cdm.matches = (struct dev_match_result *)malloc(idx->bufsize);
if (idx->ccb.cdm.matches == NULL) {
warnx("can't malloc memory for matches");
close(idx->fd);
return -1;
}
idx->ccb.cdm.num_matches = 0;
idx->i = idx->ccb.cdm.num_matches; /* to trigger buffer load */
/*
* We fetch all nodes, since we display most of them in the default
* case, and all in the verbose case.
*/
idx->ccb.cdm.num_patterns = 0;
idx->ccb.cdm.pattern_buf_len = 0;
return 1;
}
/* Helper function for scsi_give_next_adr() */
static int sg_next_enumeration_buffer(burn_drive_enumerator_t *idx)
{
/*
* We do the ioctl multiple times if necessary, in case there are
* more than 100 nodes in the EDT.
*/
if (ioctl(idx->fd, CAMIOCOMMAND, &(idx->ccb)) == -1) {
warn("error sending CAMIOCOMMAND ioctl");
return -1;
}
if ((idx->ccb.ccb_h.status != CAM_REQ_CMP)
|| ((idx->ccb.cdm.status != CAM_DEV_MATCH_LAST)
&& (idx->ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
warnx("got CAM error %#x, CDM error %d\n",
idx->ccb.ccb_h.status, idx->ccb.cdm.status);
return -1;
}
return 1;
}
static int sg_close_drive(struct burn_drive * d)
{
if (d->cam != NULL) {
cam_close_device(d->cam);
d->cam = NULL;
}
return 0;
}
/* ----------------------------------------------------------------------- */
/* 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 --------------- */
/* Operating system adapter is CAM */
/* Adapter specific handles and data */
out.cam = NULL;
/* 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);
}
/* ts A61115 */
/* ------------------------------------------------------------------------ */
/* PORTING: Public functions. These MUST be ported. */
/* ------------------------------------------------------------------------ */
/** 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 = sg_init_enumerator(idx);
if (ret<=0)
return ret;
} else if (initialize == -1) {
if(idx->fd != -1)
close(idx->fd);
idx->fd = -1;
return 0;
}
try_item:; /* This spaghetti loop keeps the number of tabs small */
/* Loop content from old scsi_enumerate_drives() */
while (idx->i >= idx->ccb.cdm.num_matches) {
ret = sg_next_enumeration_buffer(idx);
if (ret<=0)
return -1;
if (!((idx->ccb.ccb_h.status == CAM_REQ_CMP)
&& (idx->ccb.cdm.status == CAM_DEV_MATCH_MORE)) )
return 0;
idx->i = 0;
}
switch (idx->ccb.cdm.matches[idx->i].type) {
case DEV_MATCH_BUS:
break;
case DEV_MATCH_DEVICE: {
struct device_match_result* result;
result = &(idx->ccb.cdm.matches[i].result.device_result);
if (result->flags & DEV_RESULT_UNCONFIGURED)
idx->skip_device = 1;
else
idx->skip_device = 0;
break;
}
case DEV_MATCH_PERIPH: {
struct periph_match_result* result;
char buf[64];
result = &(idx->ccb.cdm.matches[i].result.periph_result);
if (idx->skip_device ||
strcmp(result->periph_name, "pass") == 0)
break;
snprintf(buf, sizeof (buf), "/dev/%s%d",
result->periph_name, result->unit_number);
if(adr_size <= strlen(buf)
return -1;
strcpy(adr, buf);
/* Found next enumerable address */
return 1;
}
default:
/* printf(stderr, "unknown match type\n"); */
break;
}
(idx->i)++;
goto try_item; /* Regular function exit is return 1 above */
}
/** 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;
char buf[64];
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;
enumerate_common(buf, idx.result->path_id, idx.result->path_id,
0, idx.result->target_id,
idx.result->target_lun);
}
sg_give_next_adr(&idx, buf, sizeof(buf), -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 (d->cam != NULL);
}
/** 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)
{
int count;
struct cam_device *cam;
if(d->cam != NULL)
return 0;
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);
return 0;
}
d->cam = cam;
fcntl(cam->fd, F_SETOWN, getpid());
d->released = 0;
return 1;
}
/** PORTING: Is mainly about the call to sg_close_drive() and wether 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->cam == NULL) {
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 done = 0;
int err;
union ccb *ccb;
if (d->cam == NULL) {
c->error = 0;
return 0;
}
c->error = 0;
ccb = cam_getccb(d->cam);
cam_fill_csio(&ccb->csio,
1, /* retries */
NULL, /* cbfncp */
CAM_DEV_QFRZDIS, /* flags */
MSG_SIMPLE_Q_TAG, /* tag_action */
NULL, /* data_ptr */
0, /* dxfer_len */
sizeof (ccb->csio.sense_data), /* sense_len */
0, /* cdb_len */
30*1000); /* timeout */
switch (c->dir) {
case TO_DRIVE:
ccb->csio.ccb_h.flags |= CAM_DIR_OUT;
break;
case FROM_DRIVE:
ccb->csio.ccb_h.flags |= CAM_DIR_IN;
break;
case NO_TRANSFER:
ccb->csio.ccb_h.flags |= CAM_DIR_NONE;
break;
}
ccb->csio.cdb_len = c->oplen;
memcpy(&ccb->csio.cdb_io.cdb_bytes, &c->opcode, c->oplen);
memset(&ccb->csio.sense_data, 0, sizeof (ccb->csio.sense_data));
if (c->page) {
ccb->csio.data_ptr = c->page->data;
if (c->dir == FROM_DRIVE) {
ccb->csio.dxfer_len = BUFFER_SIZE;
/* touch page so we can use valgrind */
memset(c->page->data, 0, BUFFER_SIZE);
} else {
/* ts A61115: removed a ssert() */
if(c->page->bytes <= 0)
return 0;
ccb->csio.dxfer_len = c->page->bytes;
}
} else {
ccb->csio.data_ptr = NULL;
ccb->csio.dxfer_len = 0;
}
do {
err = cam_send_ccb(d->cam, ccb);
if (err == -1) {
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;
}
/* 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) {
c->error = 1;
cam_freeccb(ccb);
return 1;
}
switch (scsi_error(d, c->sense, 0)) {
case RETRY:
done = 0;
break;
case FAIL:
done = 1;
c->error = 1;
break;
}
} else {
done = 1;
}
} while (!done);
cam_freeccb(ccb);
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)
{
burn_drive_enumerator_t idx;
int initialize = 1;
char buf[64];
struct periph_match_result* result;
while(1) {
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
initialize = 0;
if (ret <= 0)
break;
if (strcmp(adr, buf) != 0)
continue;
result = &(idx->ccb.cdm.matches[i].result.periph_result);
*bus_no = result->path_id;
*host_no = result->path_id;
*channel_no = 0;
*target_no = result->target_id
*lun_no = result->target_lun;
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
return 1;
}
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
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;
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);
}
/* 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
exist yet, then the directory will be inquired.
@param bytes This value gets modified 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;
struct statvfs vfsbuf;
char testpath[4096], *cpt;
long blocks;
int open_mode = O_RDWR, fd, ret;
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)) {
if(burn_sg_open_o_excl)
open_mode |= O_EXCL;
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]) {
if (statvfs(testpath, &vfsbuf) == -1)
return -2;
*bytes = add_size + ((off_t) vfsbuf.f_bsize) *
(off_t) vfsbuf.f_bavail;
}
return 1;
}

View File

@ -1,21 +1,5 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* >>> ts A61021 : for testing the new arrangement of code
please outcomment these defines : */
/* Keeps alive old enumerate_common(). New version delegates much work
to methods in drive, mmc, spc, and sbc .
*/
#define Scsi_freebsd_make_own_enumeratE 1
/* Keeps alive old sg_enumerate(). New version delegates most work to
sg_give_next_adr().
*/
#define Scsi_freebsd_old_sg_enumeratE 1
#include <assert.h>
#include <errno.h>
#include <unistd.h>
@ -34,6 +18,10 @@
#include <err.h> /* XXX */
/* ts A70909 */
#include <sys/statvfs.h>
#include "transport.h"
#include "drive.h"
#include "sg.h"
@ -47,6 +35,13 @@
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
struct burn_drive_enumeration_state {
int fd;
union ccb ccb;
unsigned int i;
int skip_device;
};
static void enumerate_common(char *fname, int bus_no, int host_no,
int channel_no, int target_no, int lun_no);
@ -55,36 +50,25 @@ int burn_drive_is_banned(char *device_address);
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
int mmc_function_spy(char * text);
debug: for tracing calls which might use open drive fds
or for catching SCSI usage of emulated drives. */
int mmc_function_spy(struct burn_drive *d, char * text);
#ifdef Scsi_freebsd_old_sg_enumeratE
/* ts A61021 : Moved most code from scsi_enumerate_drives under
sg_give_next_adr() */
/* Some helper functions for scsi_give_next_adr() */
int sg_give_next_adr(burn_drive_enumerator_t *idx,
char adr[], int adr_size, int initialize)
static int sg_init_enumerator(burn_drive_enumerator_t *idx_)
{
return (0);
}
struct burn_drive_enumeration_state *idx;
int bufsize;
int sg_is_enumerable_adr(char* adr)
{
return (0);
}
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
int *target_no, int *lun_no)
{
return (0);
}
#else /* Scsi_freebsd_old_sg_enumeratE */
/* ts A61021 : Moved most code from sg_enumerate under sg_give_next_adr() */
/* Some helper functions for sg_give_next_adr() */
static int sg_init_enumerator(burn_drive_enumerator_t *idx)
{
idx = malloc(sizeof(*idx));
if (idx == NULL) {
warnx("can't malloc memory for enumerator");
return -1;
}
idx->skip_device = 0;
if ((idx->fd = open(XPT_DEVICE, O_RDWR)) == -1) {
@ -99,12 +83,13 @@ static int sg_init_enumerator(burn_drive_enumerator_t *idx)
idx->ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
idx->ccb.ccb_h.func_code = XPT_DEV_MATCH;
idx->bufsize = sizeof(struct dev_match_result) * 100;
idx->ccb.cdm.match_buf_len = idx->bufsize;
idx->ccb.cdm.matches = (struct dev_match_result *)malloc(idx->bufsize);
bufsize = sizeof(struct dev_match_result) * 100;
idx->ccb.cdm.match_buf_len = bufsize;
idx->ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
if (idx->ccb.cdm.matches == NULL) {
warnx("can't malloc memory for matches");
close(idx->fd);
free(idx);
return -1;
}
idx->ccb.cdm.num_matches = 0;
@ -117,12 +102,28 @@ static int sg_init_enumerator(burn_drive_enumerator_t *idx)
idx->ccb.cdm.num_patterns = 0;
idx->ccb.cdm.pattern_buf_len = 0;
*idx_ = idx;
return 1;
}
static int sg_next_enumeration_buffer(burn_drive_enumerator_t *idx)
static void sg_destroy_enumerator(burn_drive_enumerator_t *idx_)
{
struct burn_drive_enumeration_state *idx = *idx_;
if(idx->fd != -1)
close(idx->fd);
free(idx->ccb.cdm.matches);
free(idx);
*idx_ = NULL;
}
static int sg_next_enumeration_buffer(burn_drive_enumerator_t *idx_)
{
struct burn_drive_enumeration_state *idx = *idx_;
/*
* We do the ioctl multiple times if necessary, in case there are
* more than 100 nodes in the EDT.
@ -153,95 +154,94 @@ static int sg_next_enumeration_buffer(burn_drive_enumerator_t *idx)
@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,
int sg_give_next_adr(burn_drive_enumerator_t *idx_,
char adr[], int adr_size, int initialize)
{
struct burn_drive_enumeration_state *idx;
int ret;
if (initialize == 1) {
ret = sg_init_enumerator(idx);
ret = sg_init_enumerator(idx_);
if (ret<=0)
return ret;
} else if (initialize == -1) {
if(idx->fd != -1)
close(idx->fd);
idx->fd = -1;
sg_destroy_enumerator(idx_);
return 0;
}
idx = *idx_;
try_item:; /* This spaghetti loop keeps the number of tabs small */
do {
if (idx->i >= idx->ccb.cdm.num_matches) {
ret = sg_next_enumeration_buffer(idx_);
if (ret<=0)
return -1;
idx->i = 0;
} else
(idx->i)++;
/* Loop content from old sg_enumerate() */
while (idx->i < idx->ccb.cdm.num_matches) {
switch (idx->ccb.cdm.matches[idx->i].type) {
case DEV_MATCH_BUS:
break;
case DEV_MATCH_DEVICE: {
struct device_match_result* result;
while (idx->i >= idx->ccb.cdm.num_matches) {
ret = sg_next_enumeration_buffer(idx);
if (ret<=0)
return -1;
if (!((idx->ccb.ccb_h.status == CAM_REQ_CMP)
&& (idx->ccb.cdm.status == CAM_DEV_MATCH_MORE)) )
return 0;
idx->i = 0;
}
result = &(idx->ccb.cdm.matches[idx->i].result.device_result);
if (result->flags & DEV_RESULT_UNCONFIGURED)
idx->skip_device = 1;
else
idx->skip_device = 0;
break;
}
case DEV_MATCH_PERIPH: {
struct periph_match_result* result;
switch (idx->ccb.cdm.matches[idx->i].type) {
case DEV_MATCH_BUS:
break;
case DEV_MATCH_DEVICE: {
struct device_match_result* result;
result = &(idx->ccb.cdm.matches[idx->i].result.periph_result);
if (idx->skip_device ||
strcmp(result->periph_name, "pass") == 0)
break;
ret = snprintf(adr, adr_size, "/dev/%s%d",
result->periph_name, result->unit_number);
if(ret >= adr_size)
return -1;
result = &(idx->ccb.cdm.matches[i].result.device_result);
if (result->flags & DEV_RESULT_UNCONFIGURED)
idx->skip_device = 1;
else
idx->skip_device = 0;
break;
}
case DEV_MATCH_PERIPH: {
struct periph_match_result* result;
char buf[64];
/* Found next enumerable address */
return 1;
result = &(idx->ccb.cdm.matches[i].result.periph_result);
if (idx->skip_device ||
strcmp(result->periph_name, "pass") == 0)
break;
snprintf(buf, sizeof (buf), "/dev/%s%d",
result->periph_name, result->unit_number);
if(adr_size <= strlen(buf)
return -1;
strcpy(adr, buf);
}
default:
/* printf(stderr, "unknown match type\n"); */
break;
}
(idx->i)++;
}
} while ((idx->ccb.ccb_h.status == CAM_REQ_CMP)
&& (idx->ccb.cdm.status == CAM_DEV_MATCH_MORE));
/* Found next enumerable address */
return 1;
}
default:
/* printf(stderr, "unknown match type\n"); */
break;
}
(idx->i)++;
goto try_item; /* Regular function exit is return 1 above */
return 0;
}
int sg_is_enumerable_adr(char* adr)
{
burn_drive_enumerator_t idx;
int initialize = 1;
int ret;
char buf[64];
ret = sg_init_enumerator(&idx);
if (ret <= 0)
return 0;
while(1) {
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
initialize = 0;
ret = sg_give_next_adr(&idx, buf, sizeof(buf), 0);
if (ret <= 0)
break;
break;
if (strcmp(adr, buf) == 0) {
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
sg_destroy_enumerator(&idx);
return 1;
}
}
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
sg_destroy_enumerator(&idx);
return (0);
}
@ -253,32 +253,32 @@ 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 ret;
char buf[64];
struct periph_match_result* result;
ret = sg_init_enumerator(&idx);
if (ret <= 0)
return 0;
while(1) {
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
initialize = 0;
ret = sg_give_next_adr(&idx, buf, sizeof(buf), 0);
if (ret <= 0)
break;
if (strcmp(adr, buf) != 0)
continue;
result = &(idx->ccb.cdm.matches[i].result.periph_result);
*bus_no = result->path_id;
*host_no = result->path_id;
*channel_no = 0;
*target_no = result->target_id
*lun_no = result->target_lun;
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
return 1;
break;
if (strcmp(path, buf) == 0) {
result = &(idx->ccb.cdm.matches[idx->i].result.periph_result);
*bus_no = result->path_id;
*host_no = result->path_id;
*channel_no = 0;
*target_no = result->target_id;
*lun_no = result->target_lun;
sg_destroy_enumerator(&idx);
return 1;
}
}
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
sg_destroy_enumerator(&idx);
return (0);
}
#endif /* ! Scsi_freebsd_old_sg_enumeratE */
int sg_close_drive(struct burn_drive * d)
{
@ -294,137 +294,30 @@ int sg_drive_is_open(struct burn_drive * d)
return (d->cam != NULL);
}
void ata_enumerate(void)
int scsi_enumerate_drives(void)
{
/* ts A61021: Only a dummy function is needed in FreeBSD */
/* The difference between sg and ata should be encapsulated
in sg-linux.c */
;
}
void sg_enumerate(void)
{
#ifdef Scsi_freebsd_old_sg_enumeratE
union ccb ccb;
int bufsize, fd;
unsigned int i;
int skip_device = 0;
if ((fd = open(XPT_DEVICE, O_RDWR)) == -1) {
warn("couldn't open %s", XPT_DEVICE);
return;
}
bzero(&ccb, sizeof(union ccb));
ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
ccb.ccb_h.func_code = XPT_DEV_MATCH;
bufsize = sizeof(struct dev_match_result) * 100;
ccb.cdm.match_buf_len = bufsize;
ccb.cdm.matches = (struct dev_match_result *)malloc(bufsize);
if (ccb.cdm.matches == NULL) {
warnx("can't malloc memory for matches");
close(fd);
return;
}
ccb.cdm.num_matches = 0;
/*
* We fetch all nodes, since we display most of them in the default
* case, and all in the verbose case.
*/
ccb.cdm.num_patterns = 0;
ccb.cdm.pattern_buf_len = 0;
/*
* We do the ioctl multiple times if necessary, in case there are
* more than 100 nodes in the EDT.
*/
do {
if (ioctl(fd, CAMIOCOMMAND, &ccb) == -1) {
warn("error sending CAMIOCOMMAND ioctl");
break;
}
if ((ccb.ccb_h.status != CAM_REQ_CMP)
|| ((ccb.cdm.status != CAM_DEV_MATCH_LAST)
&& (ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
warnx("got CAM error %#x, CDM error %d\n",
ccb.ccb_h.status, ccb.cdm.status);
break;
}
for (i = 0; i < ccb.cdm.num_matches; i++) {
switch (ccb.cdm.matches[i].type) {
case DEV_MATCH_BUS:
break;
case DEV_MATCH_DEVICE: {
struct device_match_result* result;
result = &ccb.cdm.matches[i].result.device_result;
if (result->flags & DEV_RESULT_UNCONFIGURED)
skip_device = 1;
else
skip_device = 0;
break;
}
case DEV_MATCH_PERIPH: {
struct periph_match_result* result;
char buf[64];
result = &ccb.cdm.matches[i].result.periph_result;
if (skip_device || strcmp(result->periph_name, "pass") == 0)
break;
snprintf(buf, sizeof (buf), "/dev/%s%d", result->periph_name, result->unit_number);
/* ts A51221 */
if (burn_drive_is_banned(buf))
break;
enumerate_common(buf, result->path_id, result->path_id, 0,
result->target_id, result->target_lun);
break;
}
default:
fprintf(stdout, "unknown match type\n");
break;
}
}
} while ((ccb.ccb_h.status == CAM_REQ_CMP)
&& (ccb.cdm.status == CAM_DEV_MATCH_MORE));
close(fd);
#else /* Scsi_freebsd_old_sg_enumeratE */
burn_drive_enumerator_t idx;
int initialize = 1;
int ret;
char buf[64];
struct periph_match_result* result;
ret = sg_init_enumerator(&idx);
if (ret <= 0)
return 0;
while(1) {
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
initialize = 0;
ret = sg_give_next_adr(&idx, buf, sizeof(buf), 0);
if (ret <= 0)
break;
break;
if (burn_drive_is_banned(buf))
continue;
enumerate_common(buf, idx.result->path_id, idx.result->path_id,
0, idx.result->target_id,
idx.result->target_lun);
continue;
result = &idx->ccb.cdm.matches[idx->i].result.periph_result;
enumerate_common(buf, result->path_id, result->path_id,
0, result->target_id,
result->target_lun);
}
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
#endif /* ! Scsi_freebsd_old_sg_enumeratE */
sg_destroy_enumerator(&idx);
return 1;
}
@ -481,6 +374,7 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
out.get_nwa = mmc_get_nwa;
out.close_disc = mmc_close_disc;
out.close_session = mmc_close_session;
out.close_track_session = mmc_close;
out.read_buffer_capacity = mmc_read_buffer_capacity;
out.idata = malloc(sizeof(struct burn_scsi_inquiry_data));
out.idata->valid = 0;
@ -497,7 +391,7 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy("enumerate_common : -------- doing grab");
mmc_function_spy(NULL, "enumerate_common : -------- doing grab");
/* try to get the drive info */
if (t->grab(t)) {
@ -511,7 +405,7 @@ static void enumerate_common(char *fname, int bus_no, int host_no,
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy("enumerate_common : ----- would release ");
mmc_function_spy(NULL, "enumerate_common : ----- would release ");
}
@ -559,9 +453,13 @@ int sg_grab(struct burn_drive *d)
int count;
struct cam_device *cam;
mmc_function_spy("sg_grab");
if (mmc_function_spy(d, "sg_grab") <= 0)
return 0;
assert(d->cam == NULL);
if (burn_drive_is_open(d)) {
d->released = 0;
return 1;
}
cam = cam_open_device(d->devname, O_RDWR);
if (cam == NULL) {
@ -591,16 +489,18 @@ int sg_grab(struct burn_drive *d)
int sg_release(struct burn_drive *d)
{
mmc_function_spy("sg_release");
if (mmc_function_spy(d, "sg_release") <= 0)
return 0;
if (d->cam == NULL) {
burn_print(1, "release an ungrabbed drive. die\n");
return 0;
}
mmc_function_spy("sg_release ----------- closing.");
mmc_function_spy(NULL, "sg_release ----------- closing.");
sg_close_drive(d);
d->released = 1;
return 0;
}
@ -613,7 +513,7 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
char buf[161];
snprintf(buf, sizeof (buf), "sg_issue_command d->cam=%p d->released=%d",
(void*)d->cam, d->released);
mmc_function_spy(buf);
mmc_function_spy(NULL, buf);
if (d->cam == NULL) {
c->error = 0;
@ -705,64 +605,70 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
return 1;
}
enum response scsi_error(struct burn_drive *d, unsigned char *sense,
int senselen)
/* 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
exist yet, then the directory will be inquired.
@param bytes This value gets modified 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)
{
int key, asc, ascq;
struct stat stbuf;
struct statvfs vfsbuf;
char testpath[4096], *cpt;
long blocks;
off_t add_size = 0;
senselen = senselen;
key = sense[2];
asc = sense[12];
ascq = sense[13];
burn_print(12, "CONDITION: 0x%x 0x%x 0x%x on %s %s\n",
key, asc, ascq, d->idata->vendor, d->idata->product);
switch (asc) {
case 0:
burn_print(12, "NO ERROR!\n");
return RETRY;
case 2:
burn_print(1, "not ready\n");
return RETRY;
case 4:
burn_print(1,
"logical unit is in the process of becoming ready\n");
return RETRY;
case 0x20:
if (key == 5)
burn_print(1, "bad opcode\n");
return FAIL;
case 0x21:
burn_print(1, "invalid address or something\n");
return FAIL;
case 0x24:
if (key == 5)
burn_print(1, "invalid field in cdb\n");
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
break;
return FAIL;
case 0x26:
if (key == 5)
burn_print( 1, "invalid field in parameter list\n" );
return FAIL;
case 0x28:
if (key == 6)
burn_print(1,
"Not ready to ready change, medium may have changed\n");
else
break;
return RETRY;
case 0x3A:
burn_print(12, "Medium not present in %s %s\n",
d->idata->vendor, d->idata->product);
*cpt = 0;
if (stat(testpath, &stbuf) == -1)
return -1;
d->status = BURN_DISC_EMPTY;
return FAIL;
#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);
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]) {
if (statvfs(testpath, &vfsbuf) == -1)
return -2;
*bytes = add_size + ((off_t) vfsbuf.f_bsize) *
(off_t) vfsbuf.f_bavail;
}
burn_print(1, "unknown failure\n");
burn_print(1, "key:0x%x, asc:0x%x, ascq:0x%x\n", key, asc, ascq);
return FAIL;
return 1;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,5 +1,9 @@
/* ts A61013 : It would be nice if autotools could do that job */
/* sg.c
Switcher for operating system dependent transport level modules of libburn.
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
*/
#ifdef __FreeBSD__

View File

@ -3,45 +3,17 @@
#ifndef __SG
#define __SG
#ifdef __FreeBSD__
/* >>> To hold all state information of BSD device enumeration
which are now local in sg_enumerate() . So that sg_give_next_adr()
can work in BSD and sg_enumerate() can use it. */
struct burn_drive_enumeration_state {
#include "os.h"
#ifdef Scsi_freebsd_old_sg_enumeratE
int dummy;
#else
union ccb ccb;
int bufsize, fd;
unsigned int i;
int skip_device;
#endif /* ! Scsi_freebsd_old_sg_enumeratE */
};
typedef struct burn_drive_enumeration_state burn_drive_enumerator_t;
/* see os.h for name of particular os-*.h where this is defined */
BURN_OS_DEFINE_DRIVE_ENUMERATOR_T
#else /* __FreeBSD__ */
/* <<< just for testing the C syntax */
struct burn_drive_enumeration_state {
int dummy;
};
typedef struct burn_drive_enumeration_state burn_drive_enumerator_tX;
typedef int burn_drive_enumerator_t;
#endif /* ! __FreeBSD__ */
struct burn_drive;
struct command;
enum response
{ RETRY, FAIL };
/* ts A60925 : ticket 74 */
int sg_close_drive_fd(char *fname, int driveno, int *fd, int sorry);
/* ts A60922 ticket 33 */
int sg_give_next_adr(burn_drive_enumerator_t *enm_context,
@ -50,19 +22,15 @@ int sg_is_enumerable_adr(char *adr);
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
int *target_no, int *lun_no);
/* ts A60926 : ticket 33 ++ */
int sg_open_scsi_siblings(char *fname, int driveno,
int sibling_fds[], int *sibling_count,
int host_no, int channel_no, int id_no, int lun_no);
int sg_release_siblings(int sibling_fds[], int *sibling_count);
int sg_close_drive(struct burn_drive *d);
void sg_enumerate(void);
void ata_enumerate(void);
int sg_grab(struct burn_drive *);
int sg_release(struct burn_drive *);
int sg_issue_command(struct burn_drive *, struct command *);
enum response scsi_error(struct burn_drive *, unsigned char *, int);
/* ts A61115 : formerly sg_enumerate();ata_enumerate() */
int scsi_enumerate_drives(void);
int sg_drive_is_open(struct burn_drive * d);
int burn_os_stdio_capacity(char *path, off_t *bytes);
#endif /* __SG */

View File

@ -18,10 +18,12 @@ void burn_source_free(struct burn_source *src)
enum burn_source_status burn_track_set_source(struct burn_track *t,
struct burn_source *s)
{
if (!s->read)
return BURN_SOURCE_FAILED;
s->refcount++;
t->source = s;
/* ts A61031 */
t->open_ended = (s->get_size(s) <= 0);
return BURN_SOURCE_OK;
}
@ -30,6 +32,24 @@ struct burn_source *burn_source_new(void)
struct burn_source *out;
out = calloc(1, sizeof(struct burn_source));
/* ts A70825 */
if (out == NULL)
return NULL;
memset((char *) out, 0, sizeof(struct burn_source));
out->refcount = 1;
return out;
}
/* ts A71223 */
int burn_source_cancel(struct burn_source *src)
{
if(src->read == NULL)
if(src->version > 0)
if(src->cancel != NULL)
src->cancel(src);
return 1;
}

View File

@ -5,4 +5,6 @@
struct burn_source *burn_source_new(void);
int burn_source_cancel(struct burn_source *src);
#endif /*__SOURCE*/

File diff suppressed because it is too large Load Diff

View File

@ -20,8 +20,17 @@ void spc_probe_write_modes(struct burn_drive *);
void spc_request_sense(struct burn_drive *d, struct buffer *buf);
int spc_block_type(enum burn_block_types b);
int spc_get_erase_progress(struct burn_drive *d);
/* ts A70315 : test_unit_ready with result parameters */
int spc_test_unit_ready_r(struct burn_drive *d, int *key, int *asc, int *ascq);
int spc_test_unit_ready(struct burn_drive *d);
/* ts A70315 */
/** Wait until the drive state becomes clear in or until max_sec elapsed */
int spc_wait_unit_attention(struct burn_drive *d, int max_sec, char *cmd_text,
int flag);
/* ts A61021 : the spc specific part of sg.c:enumerate_common()
*/
int spc_setup_drive(struct burn_drive *d);
@ -33,5 +42,21 @@ int spc_setup_drive(struct burn_drive *d);
int burn_scsi_setup_drive(struct burn_drive *d, int bus_no, int host_no,
int channel_no, int target_no, int lun_no, int flag);
/* ts A61115 moved from sg-*.h */
enum response { RETRY, FAIL };
enum response scsi_error(struct burn_drive *, unsigned char *, int);
/* ts A61122 */
enum response scsi_error_msg(struct burn_drive *d, unsigned char *sense,
int senselen, char msg[161],
int *key, int *asc, int *ascq);
/* ts A61030 */
/* @param flag bit0=do report conditions which are considered not an error */
int scsi_notify_error(struct burn_drive *, struct command *c,
unsigned char *sense, int senselen, int flag);
/* ts A70519 */
int scsi_init_command(struct command *c, unsigned char *opcode, int oplen);
#endif /*__SPC*/

View File

@ -40,6 +40,8 @@ struct burn_disc *burn_disc_create(void)
{
struct burn_disc *d;
d = calloc(1, sizeof(struct burn_disc));
if (d == NULL) /* ts A70825 */
return NULL;
d->refcnt = 1;
d->sessions = 0;
d->session = NULL;
@ -64,6 +66,8 @@ struct burn_session *burn_session_create(void)
{
struct burn_session *s;
s = calloc(1, sizeof(struct burn_session));
if (s == NULL) /* ts A70825 */
return NULL;
s->refcnt = 1;
s->tracks = 0;
s->track = NULL;
@ -100,10 +104,36 @@ 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;
t = calloc(1, sizeof(struct burn_track));
if (t == NULL) /* ts A70825 */
return NULL;
t->refcnt = 1;
t->indices = 0;
t->offset = 0;
@ -113,8 +143,25 @@ struct burn_track *burn_track_create(void)
t->mode = BURN_MODE1;
t->isrc.has_isrc = 0;
t->pad = 1;
/* ts A70213 */
t->fill_up_media = 0;
/* ts A70218 */
t->default_size = 0;
t->entry = NULL;
t->source = NULL;
t->eos = 0;
/* ts A61101 */
t->sourcecount = 0;
t->writecount = 0;
t->written_sectors = 0;
/* ts A61031 */
t->open_ended = 0;
t->track_data_done = 0;
t->postgap = 0;
t->pregap1 = 0;
t->pregap2 = 0;
@ -306,11 +353,20 @@ void burn_track_clear_isrc(struct burn_track *t)
int burn_track_get_sectors(struct burn_track *t)
{
int size;
/* ts A70125 : was int */
off_t size = 0;
int sectors, seclen;
seclen = burn_sector_length(t->mode);
size = t->offset + t->source->get_size(t->source) + t->tail;
if (t->source != NULL) /* ts A80808 : mending sigsegv */
size = t->offset + t->source->get_size(t->source) + t->tail;
else if(t->entry != NULL) {
/* ts A80808 : all burn_toc_entry of track starts should now
have (extensions_valid & 1), even those from CD.
*/
if (t->entry->extensions_valid & 1)
size = ((off_t) t->entry->track_blocks) * (off_t) 2048;
}
sectors = size / seclen;
if (size % seclen)
sectors++;
@ -318,6 +374,111 @@ int burn_track_get_sectors(struct burn_track *t)
return sectors;
}
/* ts A70125 */
int burn_track_set_sectors(struct burn_track *t, int sectors)
{
off_t size, seclen;
int ret;
seclen = burn_sector_length(t->mode);
size = seclen * (off_t) sectors - (off_t) t->offset - (off_t) t->tail;
if (size < 0)
return 0;
ret = t->source->set_size(t->source, size);
t->open_ended = (t->source->get_size(t->source) <= 0);
return ret;
}
/* ts A70218 , API since A70328 */
int burn_track_set_size(struct burn_track *t, off_t size)
{
if (t->source == NULL)
return 0;
if (t->source->set_size == NULL)
return 0;
t->open_ended = (size <= 0);
return t->source->set_size(t->source, size);
}
/* ts A70213 */
int burn_track_set_fillup(struct burn_track *t, int fill_up_media)
{
t->fill_up_media = fill_up_media;
if (fill_up_media)
t->open_ended = 0;
return 1;
}
/* ts A70213 */
/**
@param flag bit0= force new size even if existing track size is larger
*/
int burn_track_apply_fillup(struct burn_track *t, off_t max_size, int flag)
{
int max_sectors, ret = 2;
char msg[160];
if (t->fill_up_media <= 0)
return 2;
max_sectors = max_size / 2048;
if (burn_track_get_sectors(t) < max_sectors || (flag & 1)) {
sprintf(msg, "Setting total track size to %ds (payload %ds)\n",
max_sectors, (int) (t->source->get_size(t->source)/2048));
libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
msg, 0, 0);
ret = burn_track_set_sectors(t, max_sectors);
t->open_ended = 0;
}
return ret;
}
/* ts A61031 */
int burn_track_is_open_ended(struct burn_track *t)
{
return !!t->open_ended;
}
/* ts A70218 : API */
int burn_track_set_default_size(struct burn_track *t, off_t size)
{
t->default_size = size;
return 1;
}
/* ts A70218 */
off_t burn_track_get_default_size(struct burn_track *t)
{
return t->default_size;
}
/* ts A61101 : API function */
int burn_track_get_counters(struct burn_track *t,
off_t *read_bytes, off_t *written_bytes)
{
/*
fprintf(stderr, "libburn_experimental: sizeof(off_t)=%d\n",
sizeof(off_t));
*/
*read_bytes = t->sourcecount;
*written_bytes = t->writecount;
return 1;
}
/* ts A61031 */
int burn_track_is_data_done(struct burn_track *t)
{
return !!t->track_data_done;
}
int burn_track_get_shortage(struct burn_track *t)
{
int size;
@ -339,6 +500,7 @@ int burn_session_get_sectors(struct burn_session *s)
return sectors;
}
int burn_disc_get_sectors(struct burn_disc *d)
{
int sectors = 0, i;
@ -350,13 +512,19 @@ int burn_disc_get_sectors(struct burn_disc *d)
void burn_track_get_entry(struct burn_track *t, struct burn_toc_entry *entry)
{
memcpy(entry, t->entry, sizeof(struct burn_toc_entry));
if (t->entry == NULL)
memset(entry, 0, sizeof(struct burn_toc_entry));
else
memcpy(entry, t->entry, sizeof(struct burn_toc_entry));
}
void burn_session_get_leadout_entry(struct burn_session *s,
struct burn_toc_entry *entry)
{
memcpy(entry, s->leadout_entry, sizeof(struct burn_toc_entry));
if (s->leadout_entry == NULL)
memset(entry, 0, sizeof(struct burn_toc_entry));
else
memcpy(entry, s->leadout_entry, sizeof(struct burn_toc_entry));
}
struct burn_session **burn_disc_get_sessions(struct burn_disc *d, int *num)
@ -380,3 +548,84 @@ int burn_session_get_hidefirst(struct burn_session *session)
{
return session->hidefirst;
}
/* ts A80808 : Enhance CD toc to DVD toc */
int burn_disc_cd_toc_extensions(struct burn_disc *d, int flag)
{
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 (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;
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;
entry->start_lba = burn_msf_to_lba(entry->pmin,
entry->psec, entry->pframe);
if (tidx > 0) {
prev_entry->track_blocks =
entry->start_lba
- prev_entry->start_lba;
prev_entry->extensions_valid |= 1;
}
if (tidx == d->session[sidx]->tracks) {
entry->session_msb = 0;
entry->point_msb = 0;
entry->track_blocks = 0;
entry->extensions_valid |= 1;
}
prev_entry = entry;
}
}
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

@ -27,10 +27,29 @@ struct burn_track
int tailcount;
/** 1 means Pad with zeros, 0 means start reading the next track */
int pad;
/* ts A70213 : wether to expand this track to full available media */
int fill_up_media;
/* ts A70218 : a track size to use if it is mandarory to have some */
off_t default_size;
/** Data source */
struct burn_source *source;
/** End of Source flag */
int eos;
/* ts A61101 */
off_t sourcecount;
off_t writecount;
off_t written_sectors;
/* ts A61031 */
/** Source is of undefined length */
int open_ended;
/** End of open ended track flag : offset+payload+tail are delivered */
int track_data_done;
/** The audio/data mode for the entry. Derived from control and
possibly from reading the track's first sector. */
int mode;
@ -71,4 +90,27 @@ struct burn_disc
int burn_track_get_shortage(struct burn_track *t);
/* ts A61031 : might go to libburn.h */
int burn_track_is_open_ended(struct burn_track *t);
int burn_track_is_data_done(struct burn_track *t);
/* ts A70125 : sets overall sectors of a track: offset+payload+padding */
int burn_track_set_sectors(struct burn_track *t, int sectors);
/* ts A70218 : sets the payload size alone */
int burn_track_set_size(struct burn_track *t, off_t size);
/* ts A70213 */
int burn_track_set_fillup(struct burn_track *t, int fill_up_media);
int burn_track_apply_fillup(struct burn_track *t, off_t max_size, int flag);
/* ts A70218 */
off_t burn_track_get_default_size(struct burn_track *t);
/* ts A80808 : Enhance CD toc to DVD toc */
int burn_disc_cd_toc_extensions(struct burn_disc *d, int flag);
#endif /* BURN__STRUCTURE_H */

View File

@ -128,9 +128,14 @@ void toc_find_modes(struct burn_drive *d)
if (e && !(e->control & 4)) {
t->mode = BURN_AUDIO;
} else {
t->mode = BURN_MODE1;
/* ts A70519 : this does not work with Linux 2.4 USB because one cannot
predict the exact dxfer_size without knowing the sector type.
mem.sectors = 1;
d->read_sectors(d, lba, mem.sectors, &o, &mem);
t->mode = sector_identify(mem.data);
*/
}
}
}

View File

@ -4,20 +4,16 @@
#define __TRANSPORT
#include "libburn.h"
#include "os.h"
#include <pthread.h>
/* sg data structures */
#include <sys/types.h>
#ifdef __FreeBSD__
#define BUFFER_SIZE 65536/2
/* see os.h for name of particular os-*.h where this is defined */
#define BUFFER_SIZE BURN_OS_TRANSPORT_BUFFER_SIZE
#else /* __FreeBSD__ */
#define BUFFER_SIZE 65536
#endif /* ! __FreeBSD__ */
enum transfer_direction
{ TO_DRIVE, FROM_DRIVE, NO_TRANSFER };
@ -40,7 +36,12 @@ struct params
struct buffer
{
unsigned char data[BUFFER_SIZE];
/* ts A61219:
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). ) */
unsigned char data[BUFFER_SIZE + 4096];
int sectors;
int bytes;
};
@ -50,6 +51,7 @@ struct command
unsigned char opcode[16];
int oplen;
int dir;
int dxfer_len;
unsigned char sense[128];
int error;
int retry;
@ -64,6 +66,7 @@ struct burn_scsi_inquiry_data
int valid;
};
struct scsi_mode_data
{
int buffer_size;
@ -83,6 +86,12 @@ struct scsi_mode_data
/* ts A61021 */
int min_write_speed;
/* ts A61225 : Results from ACh GET PERFORMANCE, Type 03h
Speed values go into *_*_speed */
int min_end_lba;
int max_end_lba;
struct burn_speed_descriptor *speed_descriptors;
int cur_read_speed;
int cur_write_speed;
int retry_page_length;
@ -95,11 +104,31 @@ struct scsi_mode_data
};
#define LIBBURN_SG_MAX_SIBLINGS 16
/* ts A70112 : represents a single Formattable Capacity Descriptor as of
mmc5r03c.pdf 6.24.3.3 . There can at most be 32 of them. */
struct burn_format_descr {
/* format type: e.g 0x00 is "Full", 0x15 is "Quick" */
int type;
/* the size in bytes derived from Number of Blocks */
off_t size;
/* the Type Dependent Parameter (usually the write alignment size) */
unsigned int tdp;
};
/** Gets initialized in enumerate_common() and burn_drive_register() */
struct burn_drive
{
/* ts A70902:
0=null-emulation
1=MMC drive ,
2=stdio random read-write
3=stdio sequential write-only
*/
int drive_role;
int bus_no;
int host;
int id;
@ -107,15 +136,13 @@ struct burn_drive
int lun;
char *devname;
#if defined(__FreeBSD__)
struct cam_device* cam;
#else
int fd;
/* ts A70302: mmc5r03c.pdf 5.3.2 Physical Interface Standard */
int phys_if_std; /* 1=SCSI, 2=ATAPI, 3,4,6=FireWire, 7=SATA, 8=USB */
char phys_if_name[80]; /* MMC-5 5.3.2 table 91 , e.g. "SCSI Family" */
/* see os.h for name of particular os-*.h where this is defined */
BURN_OS_TRANSPORT_DRIVE_ELEMENTS
/* ts A60926 : trying to lock against growisofs /dev/srN, /dev/scdN */
int sibling_count;
int sibling_fds[LIBBURN_SG_MAX_SIBLINGS];
#endif
/* ts A60904 : ticket 62, contribution by elmom */
/**
@ -128,20 +155,132 @@ struct burn_drive
enum burn_disc_status status;
int erasable;
/* ts A61201 from 46h GET CONFIGURATION */
int current_profile;
char current_profile_text[80];
int current_is_cd_profile;
int current_is_supported_profile;
/* ts A70128 : MMC-to-MMC feature info from 46h for DVD-RW.
Quite internal. Regard as opaque :)
*/
/* 1 = incremental recording available, 0 = not available */
int current_has_feat21h;
/* 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
bit3= DVD-R DL supported
bit6= Buffer Under-run Free recording available (page 05h BUFE)
Value -1 indicates that no 002Fh was current in the features list.
*/
int current_feat2fh_byte4;
/* ts A70114 : whether a DVD-RW media holds an incomplete session
(which could need closing after write) */
int needs_close_session;
/* ts A71003 : whether a random write operation was done and no
synchronize chache has happened yet */
int needs_sync_cache;
/* ts A80412 : whether to use WRITE12 with Streaming bit set
rather than WRITE10. Speeds up DVD-RAM. Might help
with BD-RE */
int do_stream_recording;
/* ts A61218 from 51h READ DISC INFORMATION */
int bg_format_status; /* 0=needs format start, 1=needs format restart*/
/* ts A70108 from 23h READ FORMAT CAPACITY mmc5r03c.pdf 6.24 */
int format_descr_type; /* 1=unformatted, 2=formatted, 3=unclear */
off_t format_curr_max_size; /* meaning depends on format_descr_type */
unsigned int format_curr_blsas; /* dito */
int best_format_type;
off_t best_format_size;
/* The complete list of format descriptors as read with 23h */
int num_format_descr;
struct burn_format_descr format_descriptors[32];
volatile int released;
/* ts A61106 */
int silent_on_scsi_error;
int stdio_fd;
int nwa; /* next writeable address */
int alba; /* absolute lba */
int rlba; /* relative lba in section */
int start_lba;
int end_lba;
/* ts A70131 : from 51h READ DISC INFORMATION Number of Sessions (-1)*/
int complete_sessions;
/* ts A70129 :
from 51h READ DISC INFORMATION Last Track Number in Last Session */
int last_track_no;
/* ts A70212 : from various sources : free space on media (in bytes)
With CD this might change after particular write
parameters have been set and nwa has been inquired.
(e.g. by d->send_write_parameters() ; d->get_nwa()).
*/
off_t media_capacity_remaining;
/* 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 */
int block_types[4];
struct buffer *buffer;
struct burn_progress progress;
/* ts A70711 : keeping an eye on the drive buffer */
off_t pessimistic_buffer_free;
int pbf_altered;
int wait_for_buffer_free;
int nominal_write_speed;
unsigned int wfb_min_usec;
unsigned int wfb_max_usec;
unsigned int wfb_timeout_sec;
unsigned int wfb_min_percent;
unsigned int wfb_max_percent;
unsigned int pessimistic_writes;
unsigned int waited_writes;
unsigned int waited_tries;
unsigned int waited_usec;
volatile int cancel;
volatile enum burn_drive_status busy;
/* ts A70929 */
pid_t thread_pid;
int thread_pid_valid;
/* transport functions */
int (*grab) (struct burn_drive *);
int (*release) (struct burn_drive *);
@ -164,6 +303,7 @@ struct burn_drive
void (*unlock) (struct burn_drive *);
void (*eject) (struct burn_drive *);
void (*load) (struct burn_drive *);
int (*start_unit) (struct burn_drive *);
void (*read_disc_info) (struct burn_drive *);
void (*read_sectors) (struct burn_drive *,
int start,
@ -176,9 +316,18 @@ struct burn_drive
void (*send_write_parameters) (struct burn_drive *,
const struct burn_write_opts *);
void (*send_cue_sheet) (struct burn_drive *, struct cue_sheet *);
/* ts A70205 : Announce size of a DVD-R[W] DAO session. */
int (*reserve_track) (struct burn_drive *d, off_t size);
void (*sync_cache) (struct burn_drive *);
int (*get_erase_progress) (struct burn_drive *);
int (*get_nwa) (struct burn_drive *);
int (*get_nwa) (struct burn_drive *, int trackno, int *lba, int *nwa);
/* ts A70131 : obtain (possibly fake) TOC number and start lba of
first track in last complete session */
int (*read_multi_session_c1)(struct burn_drive *d,
int *trackno, int *start);
/* ts A61009 : removed d in favor of o->drive */
/* void (*close_disc) (struct burn_drive * d,
@ -189,6 +338,10 @@ struct burn_drive
void (*close_disc) (struct burn_write_opts * o);
void (*close_session) ( struct burn_write_opts * o);
/* ts A61029 */
void (*close_track_session) ( struct burn_drive *d,
int session, int track);
int (*test_unit_ready) (struct burn_drive * d);
void (*probe_write_modes) (struct burn_drive * d);
struct params params;
@ -200,8 +353,25 @@ struct burn_drive
/* ts A61023 : get size and free space of drive buffer */
int (*read_buffer_capacity) (struct burn_drive *d);
/* ts A61220 : format media (e.g. DVD+RW) */
int (*format_unit) (struct burn_drive *d, off_t size, int flag);
/* ts A70108 */
/* mmc5r03c.pdf 6.24 : get list of available formats */
int (*read_format_capacities) (struct burn_drive *d, int top_wanted);
/* ts A70812 */
/* mmc5r03c.pdf 6.15 : read data sectors (start and amount in LBA) */
int (*read_10) (struct burn_drive *d, int start, int amount,
struct buffer *buf);
};
/* end of generic 'drive' data structures */
/* ts A80422 : centralizing this setting for debugging purposes
*/
int burn_drive_set_media_capacity_remaining(struct burn_drive *d, off_t value);
#endif /* __TRANSPORT */

View File

@ -4,7 +4,11 @@
/* #include <a ssert.h> */
#include <stdlib.h>
#include "../version.h"
/* ts A80914 : This is unneeded. Version info comes from libburn.h.
#include "v ersion.h"
*/
#include "util.h"
#include "libburn.h"
@ -47,7 +51,8 @@ char *burn_strndup(char *s, int n)
void burn_version(int *major, int *minor, int *micro)
{
*major = BURN_MAJOR_VERSION;
*minor = BURN_MINOR_VERSION;
*micro = BURN_MICRO_VERSION;
/* ts A80408 : switched from configure.ac versioning to libburn.h versioning */
*major = burn_header_version_major;
*minor = burn_header_version_minor;
*micro = burn_header_version_micro;
}

File diff suppressed because it is too large Load Diff

View File

@ -9,12 +9,14 @@ struct burn_write_opts;
struct burn_disc;
struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o,
struct burn_session *session);
struct burn_session *session,
int nwa);
int burn_sector_length(int trackmode);
int burn_subcode_length(int trackmode);
/* ts A61009 */
int burn_disc_write_is_ok(struct burn_write_opts *o, struct burn_disc *disc);
int burn_disc_write_is_ok(struct burn_write_opts *o, struct burn_disc *disc,
int flag);
void burn_disc_write_sync(struct burn_write_opts *o, struct burn_disc *disc);
int burn_write_leadin(struct burn_write_opts *o,
@ -24,6 +26,23 @@ int burn_write_leadout(struct burn_write_opts *o,
int burn_write_session(struct burn_write_opts *o, struct burn_session *s);
int burn_write_track(struct burn_write_opts *o, struct burn_session *s,
int tnum);
int burn_write_flush(struct burn_write_opts *o);
int burn_write_flush(struct burn_write_opts *o, struct burn_track *track);
/* ts A61030 : necessary for TAO */
int burn_write_close_track(struct burn_write_opts *o, struct burn_session *s,
int tnum);
int burn_write_close_session(struct burn_write_opts *o,struct burn_session *s);
/* mmc5r03c.pdf 6.3.3.3.3: DVD-R DL: Close Function 010b: Close Session
"When the recording mode is Incremental Recording,
the disc is single session."
Enable this macro to get away from growisofs which uses Close Session
but also states "// DVD-R DL Seq has no notion of multi-session".
#define Libburn_dvd_r_dl_multi_no_close_sessioN 1
*/
#endif /* BURN__WRITE_H */

1503
libcevap/cgen.c Normal file

File diff suppressed because it is too large Load Diff

35
libcevap/cgen.h Normal file
View File

@ -0,0 +1,35 @@
#ifndef Cgen_includeD
#define Cgen_includeD Yes
struct CgeN {
char *classname;
char *structname;
char *functname;
int is_managed_list;
int is_bossless_list;
int gen_for_stic; /* 0=no smem,srgex,sfile , 1=all three, 2=smem only */
int make_ansi;
int make_lowercase;
char global_include_file[4096];
FILE *global_include_fp;
struct CtyP *elements;
struct CtyP *last_element;
int may_overwrite;
FILE *fp;
char filename[4096];
FILE *ptt_fp;
char ptt_filename[4096];
char msg[8192];
};
#endif /* Cgen_includeD */

222
libcevap/cgen.txt Normal file
View File

@ -0,0 +1,222 @@
Description of the helper program stic*/bin/cgen
cgen is copyright 2001 to 2007, Thomas Schmitt <stic-source@gmx.net>
and provided under BSD license.
Compilation:
cc -g -o cgen cgen.c ctyp.c smem.c
cgen produces a class stub in C programming language. The data structure of
the class is described by some lines which get read from stdin. The stub will
consist of four files which emerge in the current working directory:
<classname>.h public header file of the class
<classname>.c automatically generated C code of the class
plus a copy of <classname>.c.methods
<classname>_private.h private header file of the class
<classname>.c.methods safe storage for manually created functions.
From here they get copied into the generated stub.
If such a file is missing, a dummy gets created.
It will define a struct <ClassnamE> for representing the class data aspects,
construtor <Classname>_new(), destructor <Classname>_destroy(),
getter <Classname>_<element>_get() for each structure element.
Some more functions get added for particular class and element roles.
cgen normally refuses to overwrite existing files because it supposes that
those contain code added by the human programmer.
Human programmer enhancements may be explanatory comments, class specific
methods, initial element values and other special precautions within the
generated functions.
As long as the modelling phase is going on, one may store such human code
in <classname>.c.methods and may use command line option -overwrite for
modelling development cycles.
At some point of model matureness one may decide to give up cgen and the
.c.method files and to go on only with _private.h , .h and .c files.
Command line options
-no_stic prevents usage of stic_dir/s_tools/*.[ch]
-ansi generates ANSI C function heads and makes file <classname>.h hold
only public definitions: an opaque declaration of the class struct
and a list of function prototypes. The definiton of the class
struct is then in <classname>_private.h .
-global_include filename
sets the name of a file which will contain globally necessary
declarations. Currently it lists the existence of all class
structs.
-lowercase generate struct <classname> rather than struct <ClassnamE> and
function names <classname>_func() rather than <Classname>_func() .
-overwrite allows to overwrite files <classname>_private.h, <classname>.h
and <classname>.c, but not <classname>.c.methods.
Input line format:
There are two states of input: class level and element level.
Exampes are shown below with class roles and element roles.
Input starts at class level. A class level line may be one of
- Comment. A line which begins with '#' is ignored on class level.
- Empty. A line with no characters is a comment with empty text (i.e. ignored).
- Class. Options which begin with '-' and finally a word in lowercase letters
which defines the <classname>. The classname leads to a struct ClassnamE
and some class methods implemented as C functions <Classnname>_<func>().
- End of input. Line "@@@" or EOF at stdin end the program run.
After a class line, input switches to element level where a line may be:
- Comment. A line which after some white space begins with '#' is considered
a comment. The preceeding white space is ignored and the text after '#' is
eventuellay trimmed by a single blank at both ends. This text will be part
of the class struct definition within file <classname_private>.h as a single
C comment line /* ... */. The sequence of elements and comments is preserved.
An empty comment text leads to an empty line in <classname_private>.h.
- Empty. A line with no characters is a comment with empty text.
- Element. Options which begin with '-', eventual C keywords "unsigned" or
"volatile", type or "struct <NamE>", element name. This leads to a struct
element which is taken into respect in some class methods. Depending on the
options in this line, some element methods <Classnname>_<func>_<element>()
may get generated.
- End of class. A single '@' marks the end of the element list and brings
input back to class level. I.e. next is expected another class name or
"@@@" or EOF at stdin.
Input semantics:
A class can have one of two roles:
- Standalone class.
Input example:
my_class
- Listable class, which has pointers to peer instances: .prev and .next
Such classes get a list destructor <Classname>_destroy_all() which destroys
all members of a list (which is given by any of the list members).
Such a class should have a pointer *boss as first element in which case
the constructor will look like
<Classname>_new(struct <ClassnamE> **o,struct <Some_clasS> *boss,int flag);
There is a function <Classname>_link() which inserts an instance into a list
and a function <Classname>_count() which tells the number of list members.
For pseudo random access there is function <Classname>_by_idx().
Input example:
-l my_class
A modifier is defined for classes:
- Bossless. Disables a special boss-subordinate relationship which is created
if the first element of a class is a struct pointer with the name "boss".
Like
-l <classname>
-v struct Some_clasS *boss
Normally such a parameter *boss becomes part of the constructor method
<Classname>_new(struct <ClassnamE> **o, struct Some_clasS *boss, int flag);
This relationship is typical for a listable class and a single class which
is designed to host instances of that listable class. Therefore one gets a
warning if a listable class does not begin with a struct pointer *boss.
But if -b is given, then CgeN ill not include a parameter *boss into the
constructor. It will rather look normal:
<Classname>_new(struct <ClassnamE> **o, int flag);
It will not warn if the first element of a listable class is not struct
pointer *boss.
Elements have one of the following roles:
- Value. It provides only storage for a C data type (which may be a C pointer
despite the role name "value"), a getter method <Classname>_<element>_get(),
and a setter method <Classname>_<element>_set().
Input examples:
-v int i
-v int a[100]
-v char *cpt
-v struct xyz x
-v struct xyz *xpt
- Managed. This has to be a pointer to a struct <XyZ> or to char. It will not
get attached to an object by the stub's code but its destructor
<Xyz>_destroy() will be called by <Classname>_destruct(). In case of (char *)
it is supposed that a non-NULL value has been allocated by malloc().
Managed (char *) types get a setter function <Classname>_<element>_set()
which allocates memory and copies the textstring from its parameter.
Input examples:
-m struct XyZ *xyzpt
-m char *textstring
- Chainlink. A pair of prev-next-style pointers to the own class struct.
Function <Classname>_destruct() will unlink the affected instance and
put together its link partners.
Input example (there must always be two consequtive -c lines):
-c struct My_clasS *up
-c struct My_clasS *down
- List. A pair of pointers to the struct <XyZ> of a listable class. The first
one <ls> holds the start of the list, the second one <eol> holds the end.
The getter function has an additional argument idx:
<Classname>_get_<ls>(struct <ClassnamE> *o, int idx, struct <XyZ> **pt,
int flag)
idx == 0 is the start of the list, idx=1 the next element, ...
idx == -1 retrieves the last element of the list.
For insertion of list items there is provided method <Classname>_new_<ls>().
The inserted item is reachable via the getter function with idx == -1
<Classname>_destroy() instance calls <Xyz>_destroy_all(). Note that the end
pointer is always generated as private element (-p).
Input example (there must always be a -l and a -v line):
-l struct XyZ *list_start
-v struct XyZ *list_end
The availability of getter method <Classname>_get_<element>(), and setter
method <Classname>_set_<element>_set() can be controled by two modifiers:
- Readonly. Only a getter method.
Input example
-r -v int broadcasted_status
- Private. Neither getter nor setter method.
Input example
-p -v int private_value
- Bossless listable. This marks elements which are listable objects but do not
expect a boss pointer in their constructor. See above: Listable class and
the bossless modifier for classes.
Input example
-b -l struct XyZ *list
-v struct XyZ *last_in_list
- Initialization free. The class constructor will not initialize this element.
This modifier has to be used if neither NULL nor 0 are suitable
initialization values.
Example run:
rm class_x.c class_x.h class_y.c class_y.h
bin/cgen <<+
-l class_x
-r -v struct Boss_clasS *boss
-v int x
-r -v struct stat stbuf
-m struct Class_Y *y
-m char *text
-c struct Class_X *master
-c struct Class_X *slave
-b -l struct Class_X *provider
-p -v struct Class_X *last_provider
@
-b -l class_y
-r -v char providername[80]
@
+

364
libcevap/ctyp.c Normal file
View File

@ -0,0 +1,364 @@
/*
cc -g -o ctyp.c
*/
#include <sys/types.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include "smem.h"
extern char *Sfile_fgets();
extern int Sregex_string();
extern int Sregex_trimline();
#include "ctyp.h"
/* -------------------------- CtyP ----------------------- */
int Ctyp_new(objpt,link,flag)
struct CtyP **objpt;
struct CtyP *link;
int flag;
{
struct CtyP *o;
int ret;
*objpt= o= TSOB_FELD(struct CtyP,1);
if(o==NULL)
return(-1);
o->is_comment= 0;
o->is_pointer= 0;
o->is_struct= 0;
o->is_unsigned= 0;
o->is_volatile= 0;
o->array_size= 0;
o->management= 0;
o->with_getter= 1;
o->with_setter= 1;
o->bossless_list= 0;
o->no_initializer= 0;
o->dtype= NULL;
o->name= NULL;
o->prev= NULL;
o->next= NULL;
if(link!=NULL)
link->next= o;
o->prev= link;
return(1);
failed:;
Ctyp_destroy(objpt,0);
return(-1);
}
int Ctyp_destroy(objpt,flag)
struct CtyP **objpt;
int flag;
{
struct CtyP *o;
o= *objpt;
if(o==NULL)
return(0);
if(o->prev!=NULL)
o->prev->next= o->next;
if(o->next!=NULL)
o->next->prev= o->prev;
Sregex_string(&(o->dtype),NULL,0);
Sregex_string(&(o->name),NULL,0);
free((char *) o);
*objpt= NULL;
return(1);
}
int Ctyp_get_pointer_level(ct,flag)
struct CtyP *ct;
int flag;
{
return(ct->is_pointer);
}
int Ctyp_is_struct(ct,flag)
struct CtyP *ct;
int flag;
{
return(ct->is_struct);
}
int Ctyp_get_array_size(ct,flag)
struct CtyP *ct;
int flag;
{
return(ct->array_size);
}
int Ctyp_get_management(ct,flag)
struct CtyP *ct;
int flag;
{
return(ct->management);
}
int Ctyp_get_with_getter(ct,flag)
struct CtyP *ct;
int flag;
{
return(ct->with_getter);
}
int Ctyp_get_with_setter(ct,flag)
struct CtyP *ct;
int flag;
{
return(ct->with_setter);
}
int Ctyp_get_dtype(ct,text,flag)
struct CtyP *ct;
char **text; /* must point to NULL of freeable memory */
int flag;
/*
bit0=eventually prepend "struct "
*/
{
if((flag&1) && ct->is_struct) {
if(Sregex_string(text,"struct ",0)<=0)
return(-1);
} else {
if(Sregex_string(text,"",0)<=0)
return(-1);
}
if(Sregex_string(text,ct->dtype,1)<=0)
return(-1);
return(1);
}
int Ctyp_get_name(ct,text,flag)
struct CtyP *ct;
char **text; /* must point to NULL of freeable memory */
int flag;
{
if(Sregex_string(text,ct->name,0)<=0)
return(-1);
return(1);
}
int Ctyp_get_type_mod(ct,is_spointer,is_struct,array_size,flag)
struct CtyP *ct;
int *is_spointer,*is_struct,*array_size;
int flag;
{
*is_spointer= ct->is_pointer;
*is_struct= ct->is_struct;
*array_size= ct->array_size;
}
int Ctyp_new_from_line(ct,link,line,msg,flag)
struct CtyP **ct;
struct CtyP *link;
char *line;
char *msg;
int flag;
/*
bit0= make struct ClassnamE to struct classname
*/
{
struct CtyP *o;
char *cpt,*bpt;
int ret,l;
char orig_line[4096];
ret= Ctyp_new(ct,*ct,0);
if(ret<=0) {
sprintf(msg,"Failed to create CtyP object (due to lack of memory ?)");
goto ex;
}
o= *ct;
strcpy(orig_line,line);
cpt= line;
while(*cpt!=0 && isspace(*cpt)) cpt++;
if(cpt[0]=='#') {
cpt++;
if(cpt[1]==' ')
cpt++;
l= strlen(cpt);
if(cpt[0]==' ')
cpt++;
if(l>1)
if(cpt[l-1]==' ')
cpt[l-1]= 0;
if(Sregex_string(&(o->name),cpt,0)<=0)
{ret= -1; goto ex;}
o->is_comment= 1;
{ret= 1; goto ex;}
} else if(cpt[0]==0) {
if(Sregex_string(&(o->name),cpt,0)<=0)
{ret= -1; goto ex;}
o->is_comment= 1;
{ret= 1; goto ex;}
} else if(cpt[0]=='/' && cpt[1]=='*') {
sprintf(msg,
"C-style multi line comments (/* ... */) not supported yet. Use #.");
goto ex;
/* >>> */
}
cpt= line;
while(cpt[0]=='-') {
/* look for management specifiers:
-v* just a value
-m* allocated memory which needs to be freed
-c* mutual link (like prev+next)
-l* list of -m chained by mutual links prev and next
-r* read-only : no setter function
-p* private : neither setter nor getter function
-b* bossless_list : Class_new(o,flag), not Class_new(o,boss,flag)
-i* no_initializer : do not initialize element in <Class>_new()
#... line is a comment
*/
if(cpt[1]=='v' || cpt[1]=='V') {
o->management= 0;
} else if(cpt[1]=='m' || cpt[1]=='M') {
o->management= 1;
} else if(cpt[1]=='c' || cpt[1]=='C') {
o->management= 2;
if(o->prev!=NULL)
if(o->prev->management==2)
o->management= 3;
} else if(cpt[1]=='l' || cpt[1]=='L') {
o->management= 4;
} else if(cpt[1]=='r' || cpt[1]=='R') {
o->with_setter= 0;
} else if(cpt[1]=='p' || cpt[1]=='P') {
o->with_setter= 0;
o->with_getter= 0;
} else if(cpt[1]=='b' || cpt[1]=='B') {
o->bossless_list= 1;
} else if(cpt[1]=='i' || cpt[1]=='I') {
o->no_initializer= 1;
}
while(*cpt!=0 && !isspace(*cpt)) cpt++;
while(*cpt!=0 && isspace(*cpt)) cpt++;
if(*cpt==0)
goto no_name;
}
if(strncmp(cpt,"struct ",7)==0) {
o->is_struct= 1;
cpt+= 7;
} else if(strncmp(cpt,"unsigned ",9)==0) {
o->is_unsigned= 1;
cpt+= 9;
} else if(strncmp(cpt,"volatile ",9)==0) {
o->is_volatile= 1;
cpt+= 9;
if(strncmp(cpt,"unsigned ",9)==0) {
o->is_unsigned= 1;
cpt+= 9;
}
}
if(*cpt==0)
goto no_name;
while(*cpt!=0 && isspace(*cpt)) cpt++;
bpt= cpt;
while(*bpt!=0 && !isspace(*bpt)) bpt++;
if(*bpt==0)
goto no_name;
if(*bpt==0) {
no_name:;
sprintf(msg,"No name found after type description : %s",orig_line);
ret= 0; goto ex;
}
*bpt= 0;
if(Sregex_string(&(o->dtype),cpt,0)<=0)
{ret= -1; goto ex;}
if((flag&1) && o->is_struct && strlen(o->dtype)>=3)
if(isupper(o->dtype[0]) && islower(o->dtype[1]) &&
isupper(o->dtype[strlen(o->dtype)-1])) {
o->dtype[0]= tolower(o->dtype[0]);
o->dtype[strlen(o->dtype)-1]= tolower(o->dtype[strlen(o->dtype)-1]);
}
cpt= bpt+1;
while(*cpt!=0 && isspace(*cpt)) cpt++;
if(*cpt==0)
goto no_name;
for(;*cpt=='*';cpt++)
o->is_pointer++;
if(*cpt==0)
goto no_name;
bpt= strchr(cpt,'[');
if(bpt!=NULL) {
if(strchr(bpt,']')!=NULL)
*strchr(bpt,']')= 0;
sscanf(bpt+1,"%lu",&(o->array_size));
*bpt= 0;
}
if(Sregex_string(&(o->name),cpt,0)<=0)
{ret= -1; goto ex;}
if(o->management==1) {
if((!(o->is_pointer>=1 && o->is_pointer<=2)) ||
((!o->is_struct) && strcmp(o->dtype,"char")!=0 &&
(strcmp(o->dtype,"unsigned char")!=0))) {
sprintf(msg,"-m can only be applied to pointers of struct or char : %s",
orig_line);
ret= 0; goto ex;
}
}
ret= 1;
ex:;
return(ret);
}
int Ctyp_read_fp(ct,fp,msg,flag)
struct CtyP **ct;
FILE *fp;
char msg[]; /* at least [4096+256] */
int flag;
/*
bit0= make struct ClassnamE to struct classname
*/
{
int ret;
char line[4096];
struct CtyP *o;
line[0]= 0;
printf(
"[-value|-managed|-chain|-list] class element ? (e.g.: -l struct XyZ)\n");
if(Sfile_fgets(line,sizeof(line)-1,fp)==NULL)
{ret= 2; goto ex;}
printf("%s\n",line);
Sregex_trimline(line,0);
if(strcmp(line,"@")==0)
{ret= 2; goto ex;}
ret= Ctyp_new_from_line(ct,*ct,line,msg,flag&1);
if(ret<=0)
goto ex;
ret= 1;
ex:;
return(ret);
}

41
libcevap/ctyp.h Normal file
View File

@ -0,0 +1,41 @@
#ifndef Ctyp_includeD
#define Ctyp_includeD
struct CtyP {
/* if 1 : .name contains comment text, all other elements are invalid */
int is_comment;
int is_pointer; /* number of asterisks */
int is_struct;
int is_unsigned;
int is_volatile;
unsigned long array_size;
int management; /*
-v 0= just a value
-m 1= allocated memory which needs to be freed
-c 2= mutual link with the next element
-c 3= mutual link with the prev element
-l 4= list of -m , chained by -c pair named 'prev','next'
supposed to be followed by a -v of the same type
which will mark the end of the list
*/
int with_getter;
int with_setter;
int bossless_list;
int no_initializer;
char *dtype;
char *name;
struct CtyP *prev;
struct CtyP *next;
};
#endif /* Ctyp_includeD */

30
libcevap/extract_cgen_input.sh Executable file
View File

@ -0,0 +1,30 @@
#!/bin/sh
copy_mode=0
while true
do
read line
if test "$copy_mode" = "0"
then
if echo " $line" | grep '^ Cgen=' >/dev/null 2>&1
then
copy_mode=1
if echo " $line" | grep '^ Cgen=..' >/dev/null 2>&1
then
echo " $line" | sed -e 's/^ Cgen=//'
fi
elif echo " $line" | grep '^ =end Model=' >/dev/null 2>&1
then
break
fi
else
if test " $line" = " @"
then
copy_mode=0
echo "@"
else
echo " $line" | sed -e 's/^ //'
fi
fi
done

16
libcevap/libcevap_gen.sh Executable file
View File

@ -0,0 +1,16 @@
#!/bin/sh
test_dir=.
model_file=./libdax_model.txt
xtr_dir=.
cgen_dir=.
# cgen_dir=~/projekte/cdrskin_dir/libburn-develop/libcevap
cd "$test_dir" || exit 1
test -e smem.h || exit 1
cat "$model_file" | \
"$xtr_dir"/extract_cgen_input.sh | \
"$cgen_dir"/cgen -smem_local -ansi -global_include cevap_global.h \
-overwrite "$@"

BIN
libcevap/libdax_equip.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

BIN
libcevap/libdax_job.gif Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 10 KiB

944
libcevap/libdax_model.txt Normal file
View File

@ -0,0 +1,944 @@
#
# libdax is the early working name for the successor software of libburn,
# a library for writing information onto optical media, i.e. CD and DVD.
# The current working name is libcevap, refering to various kinds of roasts in
# Europe and Asia which share the property to be structured in smaller pieces.
#
# The reason for the replacement is the unclear copyright situation as well
# as libburn's sketchy original state and the subsequential evolutionary
# damages done by us in libburn code.
# This does not mean libburn is shaky. Its current state just reflects the
# virtual conflict of at least two programmer personalities and their goals.
#
#
# Please: Nobody shall take the development of libcevap as a reason for not
# programming an application which uses libburn.
# libburn works now. libcevap is planned to work in future.
#
# libcevap will replace libburn in a controlled, application friendly way.
# The first application of libcevap will be a libburn API wrapper which will
# allow to perform all API calls of libburn which are proveable to work in
# the current implementation. (Some CD stuff is not understood by us yet.
# We will have to learn.)
#
# The libburn API will be frozen when libcevap has closed up to its current
# capabilities. Nevertheless it may take profit from some of the future
# progress in libcevap (e.g. new media types).
# We hope that finally libcevap will have capabilities superior to libburn.
# This will then be a reason to port applications to the libcevap API.
#
# Application programmers are advised to encapsulate their libburn API calls
# in an own abstraction layer. The semantic concepts of burning will be
# compatible between libburn and libcevap. I.e you will have a library object
# to be started up, drives to be found and grabbed, media and their states
# to be identified, sessions, tracks, burn options to be set, blanking,
# formatting, and so on.
# Data types, function calls, and quirks will be incompatible between both
# APIs, though.
#
# -------------------------------------------------------------------------
# Originally this was a backup of text input clicketitoggled into ArgoUML
# Meanwhile it becomes an intermediate storage for attributes and
# class interconnections in the notation of my C stub generator CgeN
# (see also end of this text)
# next : work on completeness : cevapformat
# Open questions:
# - how to connect to GESTURES ? Globally ?
Model=libdax
ClassDiagram=Overview
Class=API
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=11.03.2007
Documentation=\
The API is the only layer visible to the applications. It exposes MMC concepts
which it reflects and augments by its own architectural concepts.
Subordinates=EQUIP,JOB,AUX
Cgen=\
cevapi
-r -m struct CevapequiP *equip
-r -m struct CevapjoB *job
-r -m struct CevapauX *aux
-r -m struct CevapgestureS *gestures
@
=end Class
Class=EQUIP
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=11.03.2007
Documentation=\
EQUIP represents the physical and logical equipment in reach of libdax.
This includes the system, drives, media, and their current states.
PeerToPeer=GESTURES
Boss=API
Cgen=\
cevapequip
-r -v struct CevapI *boss
-r -m struct CevapsysteM *sys
-v struct CevapgestureS *gestures
@
=end Class
Class=JOB
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=11.03.2007
Documentation=\
JOB models the tasks to be performed via libdax.
This includes disc, session, track, source, fifo, dewav, burn options.
PeerToPeer=GESTURES
Boss=API
Cgen=\
cevapjob
-r -v struct CevapI *boss
-r -m struct CevaptodO *todo
-v struct CevapgestureS *gestures
# >>>
@
=end Class
Class=AUX
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=11.03.2007
Documentation=\
AUX bundles any models which are neither EQUIP nor JOB.
This includes abort handler and message system.
PeerToPeer=GESTURES
Boss=API
Cgen=\
cevapaux
-r -v struct CevapI *boss
-v struct CevapgestureS *gestures
# >>>
@
=end Class
Class=GESTURES
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=11.03.2007
Documentation=\
GESTURES ist the procedural repertoire which interconnects EQUIP, JOB, and AUX
and also provides to them the services from the SCSI oriented layers.
PeerToPeer=EQUIP,JOB,AUX
Subordinates=SCSI_CMD
Cgen=\
cevapgestures
-r -v struct CevapI *boss
-v struct CevapequiP *equip
-v struct CevapjoB *job
-v struct CevapauX *aux
-r -m struct CevapscmD *scsi_cmd
# >>>
@
=end Class
Class=SCSI_CMD
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=11.03.2007
Documentation=\
SCSI_CMD represents the semantic part of SCSI (i.e. mainly MMC) specs.
This layer models each SCSI command that is used by libdax. It knows about
its parameters and constraints with particular equipment and jobs.
Boss=GESTURES
Subordinates=Classes with SCSI_EXEC Interface
Cgen=\
cevapscmd
-r -v struct CevapgestureS *boss
-r -m struct CevapsexeC *scsi_exec
# >>>
@
=end Class
Interface=SCSI_EXEC
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=16.03.2007
Documentation=\
SCSI_EXEC hides the difference between the implementation principle of
SCSI format+transport and the principle of SCSI service.
Boss=SCSI_CMD
Implementations=SCSI_FORMAT,SCSI_SERVICE
Cgen=\
cevapsexec
-r -v struct CevapscmD *boss
-p -v struct CevapsforM *scsi_format
-p -v struct CevapsservicE *scsi_service
-v int silent_on_scsi_error
# >>>
@
=end Interface
Class=OSDriveAspect
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=18.08.2007
Documentation=\
OSDriveAspect encapsulates operating system specific properties of an
individual drive. It shall be handed out by SCSI_EXEC via the GESTURES layer
to EquipDrive where it forms the link between cevap drive model and operating
system driver.
This class description models the implementation specific to Linux.
Cgen=\
cevaposdrv
-r -v int fd
# >>> ??? implement the sibling stuff which never worked properly ?
@
=end Class
Class=SCSI_FORMAT
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=11.03.2007
Documentation=\
SCSI_FORMAT translates parameters of SCSI commands into CDBs, takes care for
transport and decodes the reply into parameters.
Boss=SCSI_CMD via SCSI_EXEC
Subordinates=SCSI_TRANSPORT
Cgen=\
cevapsform
-r -v struct CevapsexeC *boss
-p -v struct CevapstransP *scsi_transport
# former struct command
-v unsigned char opcode[16]
-v int oplen
-v int dir
-v int dxfer_len
-v unsigned char sense[128]
-v int error
-v int retry
-v struct CevapbuffeR *page
# >>>
@
=end Class
Class=SCSI_TRANSPORT
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=11.03.2007
Documentation=\
SCSI_TRANSPORT takes a formatted CDB from SCSI_FORMAT and makes the operating
system perform a SCSI transaction. It then returns the reply data in raw form.
Boss=SCSI_FORMAT
Os_specific=yes
Cgen=\
cevapstransp
-r -v struct CevapsforM *boss
# >>>
@
=end Class
Class=SCSI_SERVICE
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=11.03.2007
Documentation=\
SCSI_SERVICE provides the combined services of SCSI_FORMAT and SCSI_TRANSPORT
via a set of parametrized functions which abstract SCSI command transactions.
Boss=SCSI_CMD via SCSI_EXEC
Os_specific=yes
Cgen=\
cevapsservice
-r -v struct CevapsexeC *boss
# >>>
@
=end Class
=end ClassDiagram=Overview
ClassDiagram=Equip_overview
Class=EquipSystem
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=16.03.2007
Documentation=\
EquipSystem is the inner root class of EQUIP. It describes the system on
which libdax is working. This includes the operating system, the system
adapter classes, the drives.
Boss=EQUIP
Subordinates=EquipDrive*N
Cgen=\
cevapsystem
-r -v struct CevapequiP *boss
-r -m char *infotext
-r -l struct CevapdrivE *drive
-p -v struct CevapdrivE *eol_drive
# >>> be boss of SCSI_CMD ? (Rather than GESTURES)
# >>>
@
=end Class
Class=EquipDrive
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=16.03.2007
Documentation=\
EquipDrive represents a drive, including its capabilities, its processing
status, the media loaded.
Subordinates=EquipMedia
Boss=EquipSystem
Cgen=\
-l cevapdrive
-r -v struct CevapsysteM *boss
# Drive number
-r -v int global_index
# Persistent system drive address
-r -m char *devname
# Traditional SCSI address parameters (-1 if not applicable)
-r -v int bus_no
-r -v int host
-r -v int id
-r -v int channel
-r -v int lun
# (former struct burn_scsi_inquiry_data idata)
# From 12h INQUIRY , spc3r23.pdf , 6.4.2 , Table 81
-r -v char vendor[9]
-r -v char product[17]
-r -v char revision[5]
# 1= above elements contain valid information
-r -v int idata_valid
# mc5r03c.pdf 5.3.2 Physical Interface Standard
# 1=SCSI, 2=ATAPI, 3,4,6=FireWire, 7=SATA, 8=USB
-r -v int phys_if_std
# MMC-5 5.3.2 table 91 , e.g. "SCSI Family"
-r -m char *phys_if_name
# System despendent aspect of the drive (e.g. int fd;)
-r -v struct CevaposdrV *system_dep_drive_info
# Result of the CD write mode x block type tests:
# Index is for write mode : 0=packet , 1=TAO , 2=SAO , 3=raw
# Bits are for block type
# Numbering as in mc5r03c.pdf 7.5.4.13 Data Block Type, Table 668 :
# 0=RAW0 (2352, Raw data)
# 1=RAW16 (2368, Raw data with P and Q Sub-channel
# 2=RAW96P (2448, Raw data with P-W Sub-channel appended)
# 3=RAW96R (2448, Raw data with raw P-W Sub-channel appended)
# 8=MODE1 (2048, ISO/IEC 10149)
# 9=MODE2R (2336, Mode 2 formless)
# 10=MODE2F1 (2048, CD-ROM XA, form 1)
# 11=MODE2F1X (2056, CD-ROM XA, form 1 plus 8 byte subheader)
# 12=MODE2F2 (2324, CD-ROM XA, form 2)
# 13=MODE2MIX (2332, CD-ROM XA, form 1, form 2, or mixed form)
-r -v int block_types[4]
# (former struct scsi_mode_data)
# Information about the drive's capabilities, obtained via 5Ah MODE SENSE
# from mode page 2Ah , mmc3r10g.pdf , 6.3.11 , Table 361
# (which is deprecated in MMC-5 E.11)
-p -v int mdata_buffer_size
-p -v int mdata_dvdram_read
-p -v int mdata_dvdram_write
-p -v int mdata_dvdr_read
-p -v int mdata_dvdr_write
-p -v int mdata_dvdrom_read
-p -v int mdata_cdrw_read
-p -v int mdata_cdrw_write
-p -v int mdata_cdr_read
-p -v int mdata_cdr_write
-p -v int mdata_max_read_speed
-p -v int mdata_max_write_speed
-p -v int madata_min_write_speed
-p -v int mdata_cur_read_speed
-p -v int mdata_cur_write_speed
-p -v int mdata_simulate
-p -v int mdata_c2_pointers
-r -v int mdata_underrun_proof
# Results from ACh GET PERFORMANCE, Type 03h
# (Speed values go into *_*_speed)
# (speed_descriptors became cevapperf which is under cevapmedia)
-p -v int min_end_lba
-p -v int max_end_lba
# from mode page 01h , mmc5r03c.pdf , 7.3.2.1 , Table 657
-p -v int mdata_retry_page_length
-p -v int mdata_retry_page_valid
# from mode page 05h , mmc5r03c.pdf , 7.5.4.1 , Table 664
-p -v int mdata_write_page_length
-p -v int mdata_write_page_valid
# 1= above elements contain valid information
-p -v int mdata_valid
# The mutex shall be used to coordinate access to the drive in situations
# where multi-threaded race conditions could disturb operations.
# E.g. lock, read busy state, interpret, set busy state, unlock
# A mere reader of the busy state does not have to lock because
# reading of the state itself is atomar.
-i -v pthread_mutex_t access_lock
# Flags from feature 002Fh feature descriptor mmc5r03c.pdf 5.3.25 :
# bit1= DVD-RW supported
# bit2= Test Write available
# bit3= DVD-R DL supported
# bit6= Buffer Under-run Free recording available (page 05h BUFE)
# Value -1 indicates that no 002Fh was current in the features list.
-r -v int current_feat2fh_byte4
# 0= drive is grabbed, 1= drive is not grabbed
-v volatile int released
# File descriptor of an eventual emulated drive
-v int stdio_fd
# >>> ???
# (do we need a drive owned buffer to carry data from call to call or what ?)
-v struct CevapbuffeR *buffer
# List of profiles as reported by the drive
-r -l struct CevapprofilE *profile
-p -v struct CevapprofilE *eol_profile
# Media currently loaded in the drive
-r -m struct CevapmediA *media
# >>> transport.h : toc_temp (what is this ? It belongs to BURN_WRITE_RAW)
# >>>
@
=end Class
Class=EquipMedia
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=16.03.2007
Documentation=\
EquipMedia represents an optical disc, including its type, its writeability,
its formatting, its available formats and performances.
Subordinates=\
EquipProfile*N,EquipFormat*N,EquipPerformance*N,EquipStatus,EquipMulticaps
Boss=EquipDrive
Cgen=\
cevapmedia
-r -v struct CevapdrivE *boss
# Volatile and/or public properties of the media
-r -m struct CevapstatuS *status
# MMC-to-MMC feature info from 46h for DVD-RW.
# Quite internal. Regard as opaque :)
# 1 = incremental recording available, 0 = not available
-r -v int current_has_feat21h
# Link Size item number 0 from feature 0021h descriptor
-r -v int current_feat21h_link_size
# Wether a DVD-RW media holds an incomplete session
# (which could need closing after write)
-v int needs_close_session
# From 51h READ DISC INFORMATION
# 0=needs format start, 1=needs format restart
-r -v int bg_format_status
# From 23h READ FORMAT CAPACITY mmc5r03c.pdf 6.24
# 1=unformatted, 2=formatted, 3=unclear
-r -v int format_descr_type
# meaning depends on format_descr_type
-r -v off_t format_curr_max_size
# dito
-r -v unsigned int format_curr_blsas
-r -v int best_format_type
-r -v off_t best_format_size
-r -l struct CevapformaT *format_descriptor
-p -v struct CevapformaT *eol_format_descriptor
# The specific capabilities and restrictions of the media
-r -m struct CevapmcapS *multicaps
# Results from ACh GET PERFORMANCE, Type 03h
# (Speed values go into drive.mdata_*_*_speed)
-r -l struct CevapperF *speed_descriptor
-p -v struct CevapperF *eol_speed_descriptor
# >>>
@
=end Class
Class=EquipProfile
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=16.03.2007
Documentation=\
EquipProfile maps a MMC profile into libdax (See mmc5r03c.pdf chapter 5).
A profile describes a set of features and may be either current, possible,
disabled, or unavailable.
Subordinates=EquipFeature*N
Boss=EquipMedia
Cgen=\
-l cevapprofile
-r -v struct CevapdrivE *boss
-r -v int is_current
-r -v int profile_code
-r -v char *profile_text
-r -v int is_cd_profile
-r -v int is_supported_profile
-r -l struct CevapfeaturE *feature
-p -v struct CevapfeaturE *eol_feature
@
=end Class
Class=EquipFeature
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=16.03.2007
Documentation=\
EquipFeature maps a MMC feature into libdax (See mmc5r03c.pdf chapter 5).
A feature describes a set of SCSI commands and (implicitely) of use cases.
Boss=EquipProfile
Cgen=\
-l cevapfeature
-r -v struct CevapprofilE *boss
# >>>
@
=end Class
Class=EquipFormat
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=
Documentation=\
EquipFormat represents a single Formattable Capacity Descriptor
as of mmc5r03c.pdf 6.24.3.3 .
Boss=EquipMedia
Cgen=\
-l cevapformat
-r -v struct CevapmediA *boss
# format type: e.g 0x00 is "Full", 0x15 is "Quick"
-r -v int type
# the size in bytes derived from Number of Blocks
-r -v off_t size
# the Type Dependent Parameter (usually the write alignment size)
-r -v unsigned int tdp
# >>>
@
=end Class
Class=EquipPerformance
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=
Documentation=\
>>> EquipPerformance
Boss=EquipMedia
Cgen=\
-l cevapperf
-r -v struct CevapmediA *boss
# >>>
@
=end Class
Class=EquipStatus
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=17.3.2007
Documentation=\
EquipStatus represents the status of media and drive. This includes
blank/appendable/closed, progress indicator.
Boss=EquipMedia
Cgen=\
cevapstatus
-r -v struct CevapmediA *boss
-v int status
-m char *status_text
-v volatile int busy
# From various sources : free space on media (in bytes)
# With CD this might change after particular write
# parameters have been set and nwa has been inquired.
-v off_t media_capacity_remaining
# Current write address during write jobs. (Next address to be written)
# <<< does this belong to JOB ?
-r -v int nwa
# if > 0 : first lba on media that is too high for write
-v int media_lba_limit
-v struct CevapprogresS *progress
# >>>
@
=end Class
Class=EquipMulticaps
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=14.8.2007
Documentation=\
EquipMulticaps represents media dependent properties and media states which
are either volatile or especially interesting to several other modules. This
includes eventually existing sessions, closure status, profile dependent
capabilities.
Boss=EquipMedia
Cgen=\
cevapmcaps
# The current profile out of the drive profile list
-v struct CevapprofilE *current_profile
# Wether the media is erasable (or overwriteable)
-v int erasable
# A description of the existing media content structure
-r -m struct CevapdisC *disc
# Start and end addresses out of ATIP.
# From 43h READ TOC/PMA/ATIP , mmc5r03c.pdf , 6.26
-r -v int start_lba
-r -v int end_lba
# From 51h READ DISC INFORMATION Number of Sessions (-1)
-v int complete_sessions
# From 51h READ DISC INFORMATION Last Track Number in Last Session
-v int last_track_no
# >>> libburn.h:struct burn_multi_caps
@
=end Class
Class=EquipTocItem
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=14.8.2007
Boss=
Cgen=\
-l cevaptocitem
-r -v struct CevapdisC *boss
-v int session
-v int valid
-v int control
# obscure info from CD TOC : possibly length of track
-v unsigned char point
-v unsigned char min
-v unsigned char sec
-v unsigned char frame
-v int pmin
-v int psec
-v int pframe
-v int start_lba
-v int track_blocks
@
=end Class
=end ClassDiagram=Equip_overview
ClassDiagram=Job_overview
Class=JobTodo
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=18.3.2007
Documentation=\
JobTodo records what is to be done during a job. This includes peripheral
actions like tray load/eject and central actions like blank, format, burn.
Subordinates=JobDisc,JobOptions
Cgen=\
cevaptodo
-v volatile int cancel
# >>>
@
=end Class
Class=JobDisc
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=18.3.2007
Documentation=\
JobDisc models a disc structure. Either one which already exists or
one which is to be created in a job run.
Subordinates=JobSession*N
Boss=JobTodo
Cgen=\
cevapdisc
-l struct CevapsessioN *session
-p -v struct CevapsessioN *eol_session
-l struct CevaptociteM *toc_entry
-p -v struct CevaptociteM *eol_toc_entry
# >>> take over services of struct burn_disc
@
=end Class
Class=JobSession
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=18.3.2007
Documentation=\
JobSession represents a recording session. A session usually bundles
several tracks. Traditionally the last session of a disc is recognized
by operating systems as the thing to be mounted.
Subordinates=JobTrack*N,JobFifo
Boss=JobDisc
Cgen=\
-l cevapsession
-r -v struct CevapdisC *boss
# >>>
-l struct CevaptracK *track
-p -v struct CevaptracK *eol_track
# >>>
@
=end Class
Class=JobTrack
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=18.3.2007
Documentation=\
JobTrack represents a track to be recorded. A track mainly is associated with
a data source but in many cases it also becomes a recognizable entity on the
target media.
Subordinates=JobBlock*N,JobTrackFilter,JobSource
Boss=JobSession
Cgen=\
-l cevaptrack
-r -v struct CevapsessioN *boss
# >>>
@
=end Class
Class=JobBlock
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=18.3.2007
Documentation=\
JobBlock represents a single output data transaction unit. On CD this is
the same as an addressable media block resp. sector. On DVD this might be
an addressable block od 2k or a packet of e.g. 32k.
Boss=JobTrack
Cgen=\
cevapblock
-v int alba
-v int rlba
# >>>
@
=end Class
Class=JobSource
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=8.4.2007
Documentation=\
JobSource represents a data source for a track. Typically this is a disk
file or a stream file descriptor like stdin.
Subordinates=JobSourceBlock*N
Boss=JobTrack
=end Class
Class=JobSourceBlock
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=8.4.2007
Documentation=\
JobSourceBlock represents a single input data transaction unit.
Boss=JobSource
=end Class
Class=JobFifo
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=8.4.2007
Documentation=\
JobFifo reads data via JobTrackFilter and buffers them until JobBlock can
accept them.
Boss=JobSession
=end Class
Class=JobTrackFilter
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=8.4.2007
Documentation=\
JobTrackFilter reads data from JobSourceBlock, processes them and presents
them to JobFifo or JobBlock. This includes stripping of .wav headers.
Boss=JobTrack
=end Class
Class=JobOptions
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=18.3.2007
Documentation=\
JobOptions bundles the adjustable parameters of a job. This includes dummy
mode, speed, appendability, blank mode, format selection, write mode,
underrun protection, random access addressing.
Boss=JobTodo
Cgen=\
cevapjobopts
# >>>
# Keeping an eye on the drive buffer
-v int wait_for_buffer_free
-v unsigned int wfb_min_usec
-v unsigned int wfb_max_usec
-v unsigned int wfb_timeout_sec
-v unsigned int wfb_min_percent
-v unsigned int wfb_max_percent
# >>> -m struct params params (used by disabled read cd funtionality)
@
=end Class
Class=JobBuffer
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=13.8.2007
Documentation=\
JobBuffer is an intermediate storage for the content of several JobBlock
or JobSourceBlock.
Cgen=\
cevapbuffer
-r -m unsigned char *data
-v int sectors
-v int bytes
@
=end Class
Class=JobProgress
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=13.8.2007
Documentation=\
JobProgress reflects the state and parts of the history of a job
Cgen=\
cevapprogress
# Keeping an eye on the drive buffer
-v int nominal_write_speed
-v off_t pessimistic_buffer_free
-v int pbf_altered
-v unsigned int pessimistic_writes
-v unsigned int waited_writes
-v unsigned int waited_tries
-v unsigned int waited_usec
# >>> the info provided by struct burn_progress
# >>>
@
=end Class
Class=
Author=Thomas Schmitt <scdbackup@gmx.net>
Version=1.0
Since=
Documentation=\
=end Class
=end ClassDiagram=Equip_overview
ClassDiagram=Gestures_overview
# >>>
=end ClassDiagram=Gestures_overview
=end Model=libdax
----------------------------------------------------------------------------
Notes:
----------------------------------------------------------------------------
Compile cgen:
( cd libcevap && cc -g -o cgen cgen.c ctyp.c smem.c )
Generate C stubs:
( cd libcevap && ./libcevap_gen.sh )
Option -lowercase would generate all lowercase struct and function names
Compile test:
( cd libcevap && ( rm a.out ; cc -g main.c cevap*.c smem.c ) )
Option -DCevap_lowercasE would tell main.c that -lowercase was used above.
----------------------------------------------------------------------------
For a description of CgeN see libcevap/cgen.txt
The generated code uses smem.[ch] out of one of my BSD licensed projects.
For a description see end of libcevap/smem.h .
------------------------------------------------------------------------

Binary file not shown.

After

Width:  |  Height:  |  Size: 12 KiB

39
libcevap/main.c Normal file
View File

@ -0,0 +1,39 @@
/*
cc -g -DCevap_lowercasE -c main.c
*/
#include <stdio.h>
#include <stdlib.h>
#include "cevapi.h"
#include "smem.h"
int main(int argc, char **argv)
{
#ifdef Cevap_lowercasE
struct cevapi *cevap= NULL;
#else
struct CevapI *cevap= NULL;
#endif
int ret;
/* full memory supervision */
Smem_set_record_items(1);
/* one short trip for testing */
#ifdef Cevap_lowercasE
ret= cevapi_new(&cevap,0);
if(ret>0)
cevapi_destroy(&cevap,0);
#else /* Cevap_lowercasE */
ret= Cevapi_new(&cevap,0);
if(ret>0)
Cevapi_destroy(&cevap,0);
#endif /* ! Cevap_lowercasE */
/* report any leaked memory */
Smem_stderr(1|2);
exit(ret<=0);
}

445
libcevap/smem.c Normal file
View File

@ -0,0 +1,445 @@
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#define Smem_included_by_smem_C
#include "smem.h"
/* ------------------------------ SmemiteM ----------------------------- */
int Smemitem_new(item,data,size,next,hash_start,flag)
struct SmemiteM **item;
char *data;
size_t size;
struct SmemiteM *next;
struct SmemiteM **hash_start;
int flag;
{
struct SmemiteM *t;
*item= t= (struct SmemiteM *) malloc(sizeof(struct SmemiteM));
if(t==NULL)
return(-1);
t->data= data;
t->size= size;
t->prev= NULL;
t->next= next;
#ifdef Smem_with_hasH
t->hash_next= NULL;
t->hash_prev= NULL;
#endif /* Smem_with_hasH */
if(next!=NULL) {
if(next->prev!=NULL) {
t->prev= next->prev;
next->prev->next= t;
}
next->prev= t;
}
#ifdef Smem_with_hasH
if(hash_start!=NULL) {
t->hash_next= *hash_start;
if(t->hash_next!=NULL) {
t->hash_next->hash_prev= t;
}
*hash_start= t;
}
#endif /* Smem_with_hasH */
return(1);
}
int Smemitem_destroy(in_item,hash_start,flag)
struct SmemiteM **in_item;
struct SmemiteM **hash_start;
int flag;
{
struct SmemiteM *item;
item= *in_item;
if(item==NULL)
return(0);
if(item==Smem_start_iteM)
Smem_start_iteM= item->next;
if(item->prev!=NULL)
item->prev->next= item->next;
if(item->next!=NULL)
item->next->prev= item->prev;
#ifdef Smem_with_hasH
if(hash_start!=NULL) {
if(item==*hash_start)
*hash_start= item->hash_next;
if(item->hash_prev!=NULL)
item->hash_prev->hash_next= item->hash_next;
if(item->hash_next!=NULL)
item->hash_next->hash_prev= item->hash_prev;
}
#endif /* Smem_with_hasH */
free((char *) item);
*in_item= NULL;
return(1);
}
int Smemitem_report(item,line,flag)
struct SmemiteM *item;
char line[1024];
int flag;
{
char *cpt;
int i,upto;
sprintf(line,"%4lu bytes at %8.8lx ",(unsigned long) item->size,
(unsigned long) item->data);
cpt= line+strlen(line);
if(item->size<=256)
upto= item->size;
else
upto= 256;
if(item->data!=NULL) {
strcpy(cpt,"= \"");
cpt+= 3;
for(i=0;i<upto;i++){
if(item->data[i]<32 || item->data[i]>=127 || item->data[i]=='\\') {
sprintf(cpt,"\\%2.2X",(unsigned char) item->data[i]);
cpt+= 3;
} else {
*(cpt++)= item->data[i];
}
}
if(i<item->size) {
sprintf(cpt,"\" [truncated]");
} else {
*(cpt++)= '"';
*cpt= 0;
}
}
return(1);
}
int Smemitem_stderr(item,flag)
struct SmemiteM *item;
int flag;
{
char line[1024];
Smemitem_report(item,line,0);
fprintf(stderr,"%s\n",line);
return(1);
}
/* -------------------------------- Smem ------------------------------ */
int Smem_protest(line,flag)
char *line;
int flag;
{
fprintf(stderr,"%s\n",line);
return(1);
}
int Smem_hashindex(ptr,flag)
char *ptr;
int flag;
{
unsigned long idx;
idx= (unsigned long) ptr;
return((idx>>Smem_hashshifT)%(Smem_hashsizE));
}
/* find a certain memory item */
struct SmemiteM *Smem_find_item(ptr,flag)
char *ptr;
int flag;
{
int misscount= 0,idx;
struct SmemiteM *current;
#ifdef Smem_with_hasH
idx= Smem_hashindex(ptr,0);
for(current= Smem_hasH[idx];current!=NULL;current= current->hash_next) {
if(current->data==ptr)
return(current);
misscount++;
}
#else /* Smem_with_hasH */
for(current= Smem_start_iteM;current!=NULL;current= current->next) {
if(current->data==ptr)
return(current);
misscount++;
}
#endif /* ! Smem_with_hasH */
return(NULL);
}
int Smem_search_and_delete(ptr,flag)
char *ptr;
int flag;
/*
bit0= revoke registration : decrement counters
*/
{
int idx;
struct SmemiteM *current;
current= Smem_find_item(ptr,0);
if(current==NULL)
return(0);
Smem_record_counT--;
Smem_record_byteS-= current->size;
idx= Smem_hashindex(ptr,0);
Smemitem_destroy(&current,&(Smem_hasH[idx]),0);
Smem_hash_counteR[idx]-= 1.0;
if(flag&1) {
Smem_malloc_counT--;
Smem_pending_counT--;
}
return(1);
}
char *Smem_malloc(size)
size_t size;
{
int idx;
char *cpt;
if(size==0) {
Smem_protest("########### smem.c : malloc(0) caught",0);
return(NULL);
}
/* if(size==1032)
cpt= NULL; / * set breakpoint here to find requests of certain size */
cpt= (char *) malloc(size);
if(cpt==NULL) {
char text[161];
sprintf(text,"########### smem.c : malloc( %lu ) returned NULL",
(unsigned long) size);
Smem_protest(text,0);
return(NULL);
}
/* if(cpt==0x080a1e20)
cpt= NULL; / * set breakpoint here to find origin of certain address */
Smem_malloc_counT++;
Smem_pending_counT++;
if(Smem_record_itemS) {
idx= Smem_hashindex(cpt,0);
Smem_hash_counteR[idx]+= 1.0;
if(Smemitem_new(&Smem_start_iteM,cpt,size,Smem_start_iteM,
&(Smem_hasH[idx]),0)<=0) {
Smem_protest(
"########### smem.c : malloc( sizeof(SmemiteM) ) returned NULL",0);
return(NULL);
}
Smem_record_counT++;
Smem_record_byteS+= size;
}
return(cpt);
}
int Smem_free(ptr)
char *ptr;
{
if(ptr==NULL) {
Smem_protest("########### smem.c : free() of NULL pointer caught",0);
return(0);
}
if(Smem_record_itemS) {
if(Smem_search_and_delete(ptr,0)<=0) {
Smem_protest("########### smem.c : free() of unrecorded pointer caught",0);
return(0);
}
}
Smem_free_counT++;
Smem_pending_counT--;
free(ptr);
return(1);
}
int Smem_report(line,flag)
char line[1024];
int flag;
{
sprintf(line,"malloc= %.f , free= %.f , pending= %.f",
Smem_malloc_counT,Smem_free_counT,Smem_pending_counT);
if(Smem_record_itemS) {
sprintf(line+strlen(line)," , bytes=%.f , records= %.f",
Smem_record_byteS,Smem_record_counT);
}
return(1);
}
int Smem_stderr(flag)
int flag;
/*
bit0= report 50 youngest pending items too
bit1= do not report if nothing is pending
*/
{
struct SmemiteM *current;
char line[1024];
int i= 0;
if(flag&2)
if(Smem_pending_counT==0.0
&& Smem_record_counT==0.0
&& Smem_record_byteS==0.0)
return(2);
Smem_report(line,0);
fprintf(stderr,"%s\n",line);
if(flag&1) {
for(current= Smem_start_iteM;current!=NULL;current= current->next) {
Smemitem_stderr(current,0);
if(++i>=50)
break;
}
if(current!=NULL)
if(current->next!=NULL)
fprintf(stderr,"[list truncated]\n");
}
return(1);
}
int Smem_set_record_items(value)
int value;
{
int i;
if(!Smem_hash_initializeD) {
for(i=0;i<Smem_hashsizE;i++) {
Smem_hasH[i]= NULL;
Smem_hash_counteR[i]= 0.0;
}
Smem_hash_initializeD= 1;
}
Smem_record_itemS= value;
return(1);
}
int Smem_is_recorded(ptr,flag)
char *ptr;
int flag;
/*
bit0= complain if return(0)
*/
{
if(Smem_record_itemS==0)
return(2);
if(Smem_find_item(ptr,0)!=NULL)
return(1);
if(flag&1)
Smem_protest("########### smem.c : free() of unrecorded pointer caught",0);
return(0);
}
/* A simple C string cloner */
int Smem_clone_string(ptr,text)
char **ptr;
char *text;
{
*ptr= Smem_malloC(strlen(text)+1);
if(*ptr==NULL)
return(-1);
strcpy(*ptr,text);
return(1);
}
/* ----------------- for usage via debugger commands --------------------- */
/* find a certain memory item */
struct SmemiteM *Smem_find_data(ptr)
char *ptr;
{
return(Smem_find_item(ptr,0));
}
/* browsing the list */
struct SmemiteM *Smem_fetch_item(step,flag)
int step;
int flag;
/*
bit0= reset cursor (and therefore address absolutely)
*/
{
static struct SmemiteM *current= NULL;
if((flag&1)||current==NULL)
current= Smem_start_iteM;
if(step>0) {
for(;current!=NULL;current= current->next) {
if(step==0)
return(current);
step--;
}
} else if(step<0) {
for(;current!=NULL;current= current->prev) {
if(step==0)
return(current);
step++;
}
} else {
return(current);
}
return(NULL);
}
int Smem_print_hash_counter() {
int i;
for(i=0;i<Smem_hashsizE;i++)
printf("%4d : %10.f\n",i,Smem_hash_counteR[i]);
return(1);
}
/* delete all recorded memory items */
int Smem_delete_all_items()
{
int ret;
while(Smem_start_iteM!=NULL) {
ret= Smem_free(Smem_start_iteM->data);
if(ret<=0)
return(0);
}
return(1);
}

165
libcevap/smem.h Normal file
View File

@ -0,0 +1,165 @@
#ifndef Smem_includeD
#define Smem_includeD
/* compile time adjustable parameters : */
/* if not defined, flat malloc() and free() is used */
#define Smem_own_functionS
#ifdef Smem_no_own_functionS
#undef Smem_own_functionS
#endif /* Smem_no_own_functionS */
/* if not defined, the record items will be smaller by 8 byte
but deletion of items may be much slower */
#define Smem_with_hasH
struct SmemiteM {
char *data;
size_t size;
struct SmemiteM *prev,*next;
struct SmemiteM *hash_prev,*hash_next;
};
#ifdef Smem_own_functionS
char *Smem_malloc();
int Smem_free();
#define TSOB_FELD(typ,anz) (typ *) Smem_malloc((anz)*sizeof(typ));
#define Smem_malloC Smem_malloc
#define Smem_freE Smem_free
#else /* Smem_own_functionS */
#define TSOB_FELD(typ,anz) (typ *) malloc((anz)*sizeof(typ));
#define Smem_malloC malloc
#define Smem_freE free
#endif /* ! Smem_own_functionS */
int Smem_set_record_items();
int Smem_stderr();
int Smem_clone_string();
#define Smem_hashsizE 251
#define Smem_hashshifT 8
#ifdef Smem_included_by_smem_C
double Smem_malloc_counT= 0.0;
double Smem_free_counT= 0.0;
double Smem_pending_counT= 0.0;
struct SmemiteM *Smem_start_iteM= NULL;
struct SmemiteM *Smem_hasH[Smem_hashsizE];
double Smem_hash_counteR[Smem_hashsizE];
/* these both init values are essential, since setting Smem_record_itemS=1
by use of Smem_set_record_items() initializes the hash array
(i do not really trust the compiler producers to have read K&R) */
int Smem_hash_initializeD= 0;
int Smem_record_itemS= 0;
double Smem_record_counT= 0.0;
double Smem_record_byteS= 0.0;
#else /* Smem_included_by_smem_C */
extern double Smem_malloc_counT;
extern double Smem_free_counT;
extern double Smem_pending_counT;
extern struct SmemiteM *Smem_start_iteM;
extern struct SmemiteM *Smem_hasH[Smem_hashsizE];
extern double Smem_hash_counteR[Smem_hashsizE];
extern int Smem_hash_initializeD;
extern int Smem_record_itemS;
extern double Smem_record_counT;
extern double Smem_record_byteS;
#endif /* ! Smem_included_by_smem_C */
#endif /* ! Smem_includeD */
/*
smem
Functions to replace malloc() and free() in order to get more control
over memory leaks or spurious errors caused by faulty usage of malloc()
and free().
Sourcecode provisions:
Use only the following macros for memory management:
TSOB_FELD(type,count) creates an array of items of given type
Smem_malloC() analogue of malloc()
Smem_freE() analogue of free()
One may #define malloc Smem_malloC resp. #define free Smem_freE
but better would be to review (and often to streamline) the sourcecode
in respect to those two functions.
Speed versus control:
In production versions, where maximum speed is required, one may undefine
the macro Smem_own_functionS in smem.h .
This causes the above macros to directly invoke malloc() and free() without
any speed reduction (and without any additional use).
Undefinitio can be done globaly by modifying smem.h or locally by defining
Smem_no_own_functionS before including smem.h .
If Smem_own_functionS remains defined, then the functions
Smem_malloc()
Smem_free()
are used rather than malloc() and free().
They count the number of calls to maintain a rough overview of memory usage.
Smem_malloc() additionally checks for 0 size and Smem_free() checks for
NULL pointers, which they both report to stderr. Eventually one should set
a breakpoint in function Smem_protest() to learn about the origin of such
messages.
A status line may be obtained by Smem_report() or printed by Smem_stderr().
As long as the variable Smem_record_itemS is set to 0, there is not very much
overhead compared with malloc() and free().
If the variable is set to 1 by Smem_set_record_items() then all malloc()
results are kept in a list where they will be deleted by their corresponding
Smem_free() calls. If a pointer is to be freed, which is not recorded in the
list then an error message will be printed to stderr. The memory will not
be freed !
This mode not only may be very slow, it also consumes at least 16 byte per
piece of data which was obtained by malloc as long as it has not been freed.
Due to the current nature of the list, large numbers of memory items are freed
much faster in the reverse order of their creation. If there is a list of
100000 strings to delete, it is very rewarding to free the youngest ones first.
A shortcut via hashing is available but consumes 24 bytes rather than 16.
(see above Smem_with_hasH )
The function Smem_is_recorded() can be used to check wether a pointer is
valid according to the list. It returns :
0 = is not in list , 1 = is in list , 2 = recording is off
If one decides to start recording malloc() results in the midst of a program
run, one has to be aware of false protests of Smem_free() if a memory piece
has been allocated before recording started. This will also cause those pieces
to be memory leaks because Smem_free() refuses to delete them. (Freeing memory
that was not obtained by malloc or was already freed previously can result in
deferred SIGSEGV or similar trouble, depending on OS and library.)
Also in that case one should stop recording before ending the program, to
avoid a lot of false complaints about longliving memory objects.
*/

View File

@ -1,11 +0,0 @@
prefix=@prefix@
exec_prefix=@exec_prefix@
libdir=@libdir@
includedir=@includedir@
Name: libisofs
Description: ISO9660 filesystem creation library
Version: @VERSION@
Requires:
Libs: -L${libdir} -lisofs
Cflags: -I${includedir}/libburn

View File

@ -1,4 +0,0 @@
all clean:
$(MAKE) -C .. -$(MAKEFLAGS) $@
.PHONY: all clean

View File

@ -1,49 +0,0 @@
pkgconfigdir=$(libdir)/pkgconfig
libincludedir=$(includedir)/libburn
##bin_PROGRAMS = test
lib_LTLIBRARIES = libisofs.la
libisofs_la_SOURCES = \
tree.h \
tree.c \
volume.h \
volume.c \
util.h \
util.c \
ecma119.c \
ecma119.h \
ecma119_tree.c \
ecma119_tree.h \
susp.h \
susp.c \
rockridge.h \
rockridge.c \
joliet.c \
joliet.h
libinclude_HEADERS = libisofs.h
##test_SOURCES = test.c
##test_LDADD = libisofs.la
##noinst_PROGRAMS = test
##test_SOURCES = test.c
##test_LDADD = $(libisofs_la_OBJECTS)
##INCLUDES = -I../burn/libburn
## ========================================================================= ##
indent_files = $(libisofs_la_SOURCES)
indent: $(indent_files)
indent -bad -bap -nbbb -nbbo -nbc -bli0 -br -bls \
-cdw -ce -cli0 -ncs -nbfda -i8 -l79 -lc79 \
-lp -saf -sai -nprs -npsl -saw -sob -ss -ut \
-sbi0 -nsc -ts8 -npcs -ncdb -fca \
$^
.PHONY: indent
## ========================================================================= ##

View File

@ -1,694 +0,0 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* vim: set noet ts=8 sts=8 sw=8 : */
#include <string.h>
#include <wchar.h>
#include <stdlib.h>
#include <time.h>
#include <assert.h>
#include <err.h>
#include "ecma119.h"
#include "ecma119_tree.h"
#include "susp.h"
#include "rockridge.h"
#include "joliet.h"
#include "volume.h"
#include "tree.h"
#include "util.h"
#include "libisofs.h"
#include "libburn/libburn.h"
/* burn-source compatible stuff */
static int
bs_read(struct burn_source *bs, unsigned char *buf, int size);
static off_t
bs_get_size(struct burn_source *bs);
static void
bs_free_data(struct burn_source *bs);
typedef void (*write_fn)(struct ecma119_write_target*, uint8_t*);
/* return true if the given state is only required for Joliet volumes */
static int
is_joliet_state(enum ecma119_write_state);
static void
next_state(struct ecma119_write_target *t);
/* write t->state_data to the buf, one block at a time */
static void
write_data_chunk(struct ecma119_write_target *t, uint8_t *buf);
/* writing functions. All these functions assume the buf is large enough */
static void
write_pri_vol_desc(struct ecma119_write_target *t, uint8_t *buf);
static void
write_vol_desc_terminator(struct ecma119_write_target *t, uint8_t *buf);
static void
write_path_table(struct ecma119_write_target *t, int l_type, uint8_t *buf);
static void
write_l_path_table(struct ecma119_write_target *t, uint8_t *buf);
static void
write_m_path_table(struct ecma119_write_target *t, uint8_t *buf);
static void
write_one_dir_record(struct ecma119_write_target *t,
struct ecma119_tree_node *dir,
int file_id,
uint8_t *buf);
static void
write_one_dir(struct ecma119_write_target *t,
struct ecma119_tree_node *dir,
uint8_t *buf);
static void
write_dirs(struct ecma119_write_target *t, uint8_t *buf);
/* wrapper functions for writing */
static void wr_system_area(struct ecma119_write_target*, uint8_t*);
static void wr_pri_vol_desc(struct ecma119_write_target*, uint8_t*);
static void wr_vol_desc_term(struct ecma119_write_target*, uint8_t*);
static void wr_l_path_table(struct ecma119_write_target*, uint8_t*);
static void wr_m_path_table(struct ecma119_write_target*, uint8_t*);
static void wr_dir_records(struct ecma119_write_target*, uint8_t*);
static void wr_files(struct ecma119_write_target*, uint8_t*);
static const write_fn writers[] =
{
NULL,
wr_system_area,
wr_pri_vol_desc,
joliet_wr_sup_vol_desc,
wr_vol_desc_term,
wr_l_path_table,
wr_m_path_table,
joliet_wr_l_path_table,
joliet_wr_m_path_table,
wr_dir_records,
joliet_wr_dir_records,
wr_files
};
/* When a writer is created, we
* 1) create an ecma119 tree
* 2) add SUSP fields (if necessary)
* 3) calculate the size and position of all nodes in the tree
* 4) finalize SUSP fields (if necessary)
*/
static void
add_susp_fields_rec(struct ecma119_write_target *t,
struct ecma119_tree_node *node)
{
size_t i;
if (!node->iso_self)
return;
rrip_add_PX(t, node);
rrip_add_NM(t, node);
rrip_add_TF(t, node);
if (node->iso_self->attrib.st_rdev)
rrip_add_PN(t, node);
if (S_ISLNK(node->iso_self->attrib.st_mode))
rrip_add_SL(t, node);
if (node->type == ECMA119_FILE && node->file.real_me)
rrip_add_CL(t, node);
if (node->type == ECMA119_DIR
&& node->dir.real_parent != node->parent) {
rrip_add_RE(t, node);
rrip_add_PL(t, node);
}
susp_add_CE(t, node);
if (node->type == ECMA119_DIR) {
for (i = 0; i < node->dir.nchildren; i++) {
add_susp_fields_rec(t, node->dir.children[i]);
}
}
}
static void
add_susp_fields(struct ecma119_write_target *t)
{
susp_add_SP(t, t->root);
rrip_add_ER(t, t->root);
add_susp_fields_rec(t, t->root);
}
/**
* Fill out the dir.len and dir.CE_len fields for each
* ecma119_tree_node that is a directory. Also calculate the total number of
* directories and the number of files for which we need to write out data.
* (dirlist_len and filelist_len)
*/
static void
calc_dir_size(struct ecma119_write_target *t,
struct ecma119_tree_node *dir)
{
size_t i;
assert(dir->type == ECMA119_DIR);
t->dirlist_len++;
dir->dir.len = 34 + dir->dir.self_susp.non_CE_len
+ 34 + dir->dir.parent_susp.non_CE_len;
dir->dir.CE_len = dir->dir.self_susp.CE_len
+ dir->dir.parent_susp.CE_len;
for (i = 0; i < dir->dir.nchildren; i++) {
struct ecma119_tree_node *ch = dir->dir.children[i];
dir->dir.len += ch->dirent_len + ch->susp.non_CE_len;
dir->dir.CE_len += ch->susp.CE_len;
}
t->total_dir_size += round_up(dir->dir.len + dir->dir.CE_len,
t->block_size);
for (i = 0; i < dir->dir.nchildren; i++) {
struct ecma119_tree_node *ch = dir->dir.children[i];
struct iso_tree_node *iso = ch->iso_self;
if (ch->type == ECMA119_DIR) {
calc_dir_size(t, ch);
} else if (iso && iso->attrib.st_size
&& iso->loc.type == LIBISO_FILESYS
&& iso->loc.path) {
t->filelist_len++;
}
}
}
/**
* Fill out the block field in each ecma119_tree_node that is a directory and
* fill out t->dirlist.
*/
static void
calc_dir_pos(struct ecma119_write_target *t,
struct ecma119_tree_node *dir)
{
size_t i;
assert(dir->type == ECMA119_DIR);
/* we don't need to set iso_self->block since each tree writes
* its own directories */
dir->block = t->curblock;
t->curblock += div_up(dir->dir.len + dir->dir.CE_len, t->block_size);
t->dirlist[t->curfile++] = dir;
for (i = 0; i < dir->dir.nchildren; i++) {
struct ecma119_tree_node *ch = dir->dir.children[i];
if (ch->type == ECMA119_DIR)
calc_dir_pos(t, ch);
}
/* reset curfile when we're finished */
if (!dir->parent) {
t->curfile = 0;
}
}
/**
* Fill out the block field for each ecma119_tree_node that is a file and fill
* out t->filelist.
*/
static void
calc_file_pos(struct ecma119_write_target *t,
struct ecma119_tree_node *dir)
{
size_t i;
assert(dir->type == ECMA119_DIR);
for (i = 0; i < dir->dir.nchildren; i++) {
struct ecma119_tree_node *ch = dir->dir.children[i];
if (ch->type == ECMA119_FILE && ch->iso_self) {
struct iso_tree_node *iso = ch->iso_self;
off_t size = iso->attrib.st_size;
iso->block = ch->block = t->curblock;
t->curblock += div_up(size, t->block_size);
if (size && iso->loc.type == LIBISO_FILESYS
&& iso->loc.path)
t->filelist[t->curfile++] = ch;
}
}
for (i = 0; i < dir->dir.nchildren; i++) {
struct ecma119_tree_node *ch = dir->dir.children[i];
if (ch->type == ECMA119_DIR)
calc_file_pos(t, ch);
}
/* reset curfile when we're finished */
if (!dir->parent) {
t->curfile = 0;
}
}
struct ecma119_write_target*
ecma119_target_new(struct iso_volset *volset,
int volnum,
int level,
int flags)
{
struct ecma119_write_target *t =
calloc(1, sizeof(struct ecma119_write_target));
size_t i, j, cur;
struct iso_tree_node *iso_root = volset->volume[volnum]->root;
volset->refcount++;
t->root = ecma119_tree_create(t, iso_root);
t->joliet = (flags & ECMA119_JOLIET) ? 1 : 0;
if (t->joliet)
t->joliet_root = joliet_tree_create(t, iso_root);
t->volset = volset;
t->volnum = volnum;
t->now = time(NULL);
t->rockridge = (flags & ECMA119_ROCKRIDGE) ? 1 : 0;
t->iso_level = level;
t->block_size = 2048;
if (t->rockridge)
add_susp_fields(t);
calc_dir_size(t, t->root);
if (t->joliet) {
joliet_calc_dir_size(t, t->joliet_root);
t->pathlist_joliet = calloc(1, sizeof(void*) * t->dirlist_len);
t->dirlist_joliet = calloc(1, sizeof(void*) * t->dirlist_len);
}
t->dirlist = calloc(1, sizeof(void*) * t->dirlist_len);
t->pathlist = calloc(1, sizeof(void*) * t->dirlist_len);
t->filelist = calloc(1, sizeof(void*) * t->filelist_len);
/* fill out the pathlist */
t->pathlist[0] = t->root;
t->path_table_size = 10; /* root directory record */
cur = 1;
for (i = 0; i < t->dirlist_len; i++) {
struct ecma119_tree_node *dir = t->pathlist[i];
for (j = 0; j < dir->dir.nchildren; j++) {
struct ecma119_tree_node *ch = dir->dir.children[j];
if (ch->type == ECMA119_DIR) {
size_t len = 8 + strlen(ch->name);
t->pathlist[cur++] = ch;
t->path_table_size += len + len % 2;
}
}
}
t->curblock = 16 /* system area */
+ 1 /* volume desc */
+ 1; /* volume desc terminator */
if (t->joliet) /* supplementary vol desc */
t->curblock += div_up (2048, t->block_size);
t->l_path_table_pos = t->curblock;
t->curblock += div_up(t->path_table_size, t->block_size);
t->m_path_table_pos = t->curblock;
t->curblock += div_up(t->path_table_size, t->block_size);
if (t->joliet) {
joliet_prepare_path_tables(t);
t->l_path_table_pos_joliet = t->curblock;
t->curblock += div_up(t->path_table_size_joliet, t->block_size);
t->m_path_table_pos_joliet = t->curblock;
t->curblock += div_up(t->path_table_size_joliet, t->block_size);
}
calc_dir_pos(t, t->root);
if (t->joliet)
joliet_calc_dir_pos(t, t->joliet_root);
calc_file_pos(t, t->root);
if (t->joliet)
joliet_update_file_pos (t, t->joliet_root);
if (t->rockridge) {
susp_finalize(t, t->root);
rrip_finalize(t, t->root);
}
t->total_size = t->curblock * t->block_size;
t->vol_space_size = t->curblock;
/* prepare for writing */
t->curblock = 0;
t->state = ECMA119_WRITE_SYSTEM_AREA;
return t;
}
static int
is_joliet_state(enum ecma119_write_state state)
{
return state == ECMA119_WRITE_SUP_VOL_DESC_JOLIET
|| state == ECMA119_WRITE_L_PATH_TABLE_JOLIET
|| state == ECMA119_WRITE_M_PATH_TABLE_JOLIET
|| state == ECMA119_WRITE_DIR_RECORDS_JOLIET;
}
static void
next_state(struct ecma119_write_target *t)
{
t->state++;
while (!t->joliet && is_joliet_state(t->state))
t->state++;
printf ("now in state %d, curblock=%d\n", (int)t->state, (int)t->curblock);
}
static void
wr_system_area(struct ecma119_write_target *t, uint8_t *buf)
{
memset(buf, 0, t->block_size);
if (t->curblock == 15) {
next_state(t);
}
}
static void
wr_pri_vol_desc(struct ecma119_write_target *t, uint8_t *buf)
{
ecma119_start_chunking(t, write_pri_vol_desc, 2048, buf);
}
static void
wr_vol_desc_term(struct ecma119_write_target *t, uint8_t *buf)
{
ecma119_start_chunking(t, write_vol_desc_terminator, 2048, buf);
}
static void
wr_l_path_table(struct ecma119_write_target *t, uint8_t *buf)
{
ecma119_start_chunking(t, write_l_path_table, t->path_table_size, buf);
}
static void
wr_m_path_table(struct ecma119_write_target *t, uint8_t *buf)
{
ecma119_start_chunking(t, write_m_path_table, t->path_table_size, buf);
}
static void
wr_dir_records(struct ecma119_write_target *t, uint8_t *buf)
{
ecma119_start_chunking(t, write_dirs, t->total_dir_size, buf);
}
static void
wr_files(struct ecma119_write_target *t, uint8_t *buf)
{
struct state_files *f_st = &t->state_files;
size_t nread;
struct ecma119_tree_node *f = t->filelist[f_st->file];
const char *path = f->iso_self->loc.path;
if (!f_st->fd) {
f_st->data_len = f->iso_self->attrib.st_size;
f_st->fd = fopen(path, "r");
if (!f_st->fd)
err(1, "couldn't open %s for reading", path);
assert(t->curblock == f->block);
}
nread = fread(buf, 1, t->block_size, f_st->fd);
f_st->pos += t->block_size;
if (nread < 0)
warn("problem reading from %s", path);
else if (nread != t->block_size && f_st->pos < f_st->data_len)
warnx("incomplete read from %s", path);
if (f_st->pos >= f_st->data_len) {
fclose(f_st->fd);
f_st->fd = 0;
f_st->pos = 0;
f_st->file++;
if (f_st->file >= t->filelist_len)
next_state(t);
}
}
static void
write_pri_vol_desc(struct ecma119_write_target *t, uint8_t *buf)
{
struct ecma119_pri_vol_desc *vol = (struct ecma119_pri_vol_desc*)buf;
struct iso_volume *volume = t->volset->volume[t->volnum];
char *vol_id = str2ascii(volume->volume_id);
char *pub_id = str2ascii(volume->publisher_id);
char *data_id = str2ascii(volume->data_preparer_id);
char *volset_id = str2ascii(t->volset->volset_id);
vol->vol_desc_type[0] = 1;
memcpy(vol->std_identifier, "CD001", 5);
vol->vol_desc_version[0] = 1;
memcpy(vol->system_id, "SYSID", 5);
if (vol_id)
strncpy((char*)vol->volume_id, vol_id, 32);
iso_bb(vol->vol_space_size, t->vol_space_size, 4);
iso_bb(vol->vol_set_size, t->volset->volset_size, 2);
iso_bb(vol->vol_seq_number, t->volnum + 1, 2);
iso_bb(vol->block_size, t->block_size, 2);
iso_bb(vol->path_table_size, t->path_table_size, 4);
iso_lsb(vol->l_path_table_pos, t->l_path_table_pos, 4);
iso_msb(vol->m_path_table_pos, t->m_path_table_pos, 4);
write_one_dir_record(t, t->root, 3, vol->root_dir_record);
strncpy((char*)vol->vol_set_id, volset_id, 128);
strncpy((char*)vol->publisher_id, pub_id, 128);
strncpy((char*)vol->data_prep_id, data_id, 128);
strncpy((char*)vol->application_id, "APPID", 128);
iso_datetime_17(vol->vol_creation_time, t->now);
iso_datetime_17(vol->vol_modification_time, t->now);
iso_datetime_17(vol->vol_effective_time, t->now);
vol->file_structure_version[0] = 1;
free(vol_id);
free(volset_id);
free(pub_id);
free(data_id);
}
static void
write_vol_desc_terminator(struct ecma119_write_target *t, uint8_t *buf)
{
struct ecma119_vol_desc_terminator *vol =
(struct ecma119_vol_desc_terminator*) buf;
vol->vol_desc_type[0] = 255;
memcpy(vol->std_identifier, "CD001", 5);
vol->vol_desc_version[0] = 1;
}
static void
write_path_table(struct ecma119_write_target *t, int l_type, uint8_t *buf)
{
void (*write_int)(uint8_t*, uint32_t, int) = l_type ? iso_lsb
: iso_msb;
size_t i;
struct ecma119_path_table_record *rec;
struct ecma119_tree_node *dir;
int parent = 0;
for (i = 0; i < t->dirlist_len; i++) {
dir = t->pathlist[i];
while ((i) && t->pathlist[parent] != dir->parent)
parent++;
assert(parent < i || i == 0);
rec = (struct ecma119_path_table_record*) buf;
rec->len_di[0] = dir->parent ? (uint8_t) strlen(dir->name) : 1;
rec->len_xa[0] = 0;
write_int(rec->block, dir->block, 4);
write_int(rec->parent, parent + 1, 2);
if (dir->parent)
memcpy(rec->dir_id, dir->name, rec->len_di[0]);
buf += 8 + rec->len_di[0] + (rec->len_di[0] % 2);
}
}
static void
write_l_path_table(struct ecma119_write_target *t, uint8_t *buf)
{
write_path_table(t, 1, buf);
}
static void
write_m_path_table(struct ecma119_write_target *t, uint8_t *buf)
{
write_path_table(t, 0, buf);
}
/* if file_id is >= 0, we use it instead of the filename. As a magic number,
* file_id == 3 means that we are writing the root directory record (in order
* to distinguish it from the "." entry in the root directory) */
static void
write_one_dir_record(struct ecma119_write_target *t,
struct ecma119_tree_node *node,
int file_id,
uint8_t *buf)
{
uint8_t len_dr = (file_id >= 0) ? 34 : node->dirent_len;
uint8_t len_fi = (file_id >= 0) ? 1 : strlen(node->name);
uint8_t f_id = (uint8_t) ((file_id == 3) ? 0 : file_id);
uint8_t *name = (file_id >= 0) ? &f_id : (uint8_t*)node->name;
uint32_t len = (node->type == ECMA119_DIR) ? node->dir.len
: node->file.real_me ? 0 : node->iso_self->attrib.st_size;
struct ecma119_dir_record *rec = (struct ecma119_dir_record*)buf;
/* we don't write out susp fields for the root node */
if (t->rockridge) {
if (file_id == 0) {
susp_write(t, &node->dir.self_susp, &buf[len_dr]);
len_dr += node->dir.self_susp.non_CE_len;
} else if (file_id == 1) {
susp_write(t, &node->dir.parent_susp, &buf[len_dr]);
len_dr += node->dir.parent_susp.non_CE_len;
} else if (file_id < 0) {
susp_write(t, &node->susp, &buf[len_dr]);
len_dr += node->susp.non_CE_len;
}
}
if (file_id == 1 && node->parent)
node = node->parent;
rec->len_dr[0] = len_dr;
iso_bb(rec->block, node->block, 4);
iso_bb(rec->length, len, 4);
iso_datetime_7(rec->recording_time, t->now);
rec->flags[0] = (node->type == ECMA119_DIR) ? 2 : 0;
iso_bb(rec->vol_seq_number, t->volnum + 1, 2);
rec->len_fi[0] = len_fi;
memcpy(rec->file_id, name, len_fi);
}
static void
write_one_dir(struct ecma119_write_target *t,
struct ecma119_tree_node *dir,
uint8_t *buf)
{
size_t i;
uint8_t *orig_buf = buf;
assert(dir->type == ECMA119_DIR);
/* write the "." and ".." entries first */
write_one_dir_record(t, dir, 0, buf);
buf += ((struct ecma119_dir_record*) buf)->len_dr[0];
write_one_dir_record(t, dir, 1, buf);
buf += ((struct ecma119_dir_record*) buf)->len_dr[0];
for (i = 0; i < dir->dir.nchildren; i++) {
write_one_dir_record(t, dir->dir.children[i], -1, buf);
buf += ((struct ecma119_dir_record*) buf)->len_dr[0];
}
/* write the susp continuation areas */
if (t->rockridge) {
susp_write_CE(t, &dir->dir.self_susp, buf);
buf += dir->dir.self_susp.CE_len;
susp_write_CE(t, &dir->dir.parent_susp, buf);
buf += dir->dir.parent_susp.CE_len;
for (i = 0; i < dir->dir.nchildren; i++) {
susp_write_CE(t, &dir->dir.children[i]->susp, buf);
buf += dir->dir.children[i]->susp.CE_len;
}
}
assert (buf - orig_buf == dir->dir.len + dir->dir.CE_len);
}
static void
write_dirs(struct ecma119_write_target *t, uint8_t *buf)
{
size_t i;
struct ecma119_tree_node *dir;
for (i = 0; i < t->dirlist_len; i++) {
dir = t->dirlist[i];
write_one_dir(t, dir, buf);
buf += round_up(dir->dir.len + dir->dir.CE_len, t->block_size);
}
}
void
ecma119_start_chunking(struct ecma119_write_target *t,
write_fn writer,
off_t data_size,
uint8_t *buf)
{
if (data_size != t->state_data_size) {
data_size = round_up(data_size, t->block_size);
t->state_data = realloc(t->state_data, data_size);
t->state_data_size = data_size;
}
memset(t->state_data, 0, t->state_data_size);
t->state_data_off = 0;
t->state_data_valid = 1;
writer(t, t->state_data);
write_data_chunk(t, buf);
}
static void
write_data_chunk(struct ecma119_write_target *t, uint8_t *buf)
{
memcpy(buf, t->state_data + t->state_data_off, t->block_size);
t->state_data_off += t->block_size;
if (t->state_data_off >= t->state_data_size) {
assert (t->state_data_off <= t->state_data_size);
t->state_data_valid = 0;
next_state(t);
}
}
static int
bs_read(struct burn_source *bs, unsigned char *buf, int size)
{
struct ecma119_write_target *t = (struct ecma119_write_target*)bs->data;
if (size != t->block_size) {
warnx("you must read data in block-sized chunks (%d bytes)",
(int)t->block_size);
return 0;
} else if (t->curblock >= t->vol_space_size) {
return 0;
}
if (t->state_data_valid)
write_data_chunk(t, buf);
else
writers[t->state](t, buf);
t->curblock++;
return size;
}
static off_t
bs_get_size(struct burn_source *bs)
{
struct ecma119_write_target *t = (struct ecma119_write_target*)bs->data;
return t->total_size;
}
static void
bs_free_data(struct burn_source *bs)
{
struct ecma119_write_target *t = (struct ecma119_write_target*)bs->data;
ecma119_tree_free(t->root);
free(t->dirlist);
free(t->pathlist);
free(t->dirlist_joliet);
free(t->pathlist_joliet);
free(t->filelist);
free(t->state_data);
if (t->state_files.fd)
fclose(t->state_files.fd);
}
struct burn_source *iso_source_new_ecma119(struct iso_volset *volset,
int volnum,
int level,
int flags)
{
struct burn_source *ret = calloc(1, sizeof(struct burn_source));
ret->refcount = 1;
ret->read = bs_read;
ret->get_size = bs_get_size;
ret->free_data = bs_free_data;
ret->data = ecma119_target_new(volset, volnum, level, flags);
return ret;
}

View File

@ -1,267 +0,0 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* vim: set noet ts=8 sts=8 sw=8 : */
/**
* \file ecma119.h
*
* Structures and definitions used for writing an emca119 (ISO9660) compatible
* volume.
*/
#ifndef LIBISO_ECMA119_H
#define LIBISO_ECMA119_H
#include <sys/time.h>
#include <stdint.h>
#include <stdio.h> /* for FILE */
#include <sys/types.h>
#include "susp.h"
struct ecma119_tree_node;
struct joliet_tree_node;
/**
* The possible states that the ecma119 writer can be in.
*/
enum ecma119_write_state
{
ECMA119_WRITE_BEFORE,
ECMA119_WRITE_SYSTEM_AREA,
ECMA119_WRITE_PRI_VOL_DESC,
ECMA119_WRITE_SUP_VOL_DESC_JOLIET,
ECMA119_WRITE_VOL_DESC_TERMINATOR,
ECMA119_WRITE_L_PATH_TABLE,
ECMA119_WRITE_M_PATH_TABLE,
ECMA119_WRITE_L_PATH_TABLE_JOLIET,
ECMA119_WRITE_M_PATH_TABLE_JOLIET,
ECMA119_WRITE_DIR_RECORDS,
ECMA119_WRITE_DIR_RECORDS_JOLIET,
ECMA119_WRITE_FILES,
ECMA119_WRITE_DONE
};
/**
* Data describing the state of the ecma119 writer. Everything here should be
* considered private!
*/
struct ecma119_write_target
{
struct ecma119_tree_node *root;
struct joliet_tree_node *joliet_root;
struct iso_volset *volset;
int volnum;
time_t now; /**< Time at which writing began. */
off_t total_size; /**< Total size of the output. This only
* includes the current volume. */
uint32_t vol_space_size;
unsigned int rockridge:1;
unsigned int joliet:1;
unsigned int iso_level:2;
int curblock;
uint16_t block_size;
uint32_t path_table_size;
uint32_t path_table_size_joliet;
uint32_t l_path_table_pos;
uint32_t m_path_table_pos;
uint32_t l_path_table_pos_joliet;
uint32_t m_path_table_pos_joliet;
uint32_t total_dir_size;
uint32_t total_dir_size_joliet;
struct ecma119_tree_node **dirlist;
/**< A pre-order list of directories
* (this is the order in which we write
* out directory records).
*/
struct ecma119_tree_node **pathlist;
/**< A breadth-first list of
* directories. This is used for
* writing out the path tables.
*/
size_t dirlist_len; /**< The length of the previous 2 lists.
*/
struct ecma119_tree_node **filelist;
/**< A pre-order list of files with
* non-NULL paths and non-zero sizes.
*/
size_t filelist_len; /* Length of the previous list. */
int curfile; /**< Used as a helper field for writing
out filelist and dirlist */
/* Joliet versions of the above lists. Since Joliet doesn't require
* directory relocation, the order of these lists might be different
* from the lists above (but they will be the same length).
*/
struct joliet_tree_node **dirlist_joliet;
struct joliet_tree_node **pathlist_joliet;
enum ecma119_write_state state; /* The current state of the writer. */
/* Most writers work by
* 1) making sure state_data is big enough for their data
* 2) writing _all_ their data into state_data
* 3) relying on write_data_chunk to write the data block
* by block.
*/
uint8_t *state_data;
off_t state_data_size;
off_t state_data_off;
int state_data_valid;
/* for writing out files */
struct state_files {
off_t pos; /* The number of bytes we have written
* so far in the current file.
*/
off_t data_len;/* The number of bytes in the currently
* open file.
*/
FILE *fd; /* The currently open file. */
int file; /* The index in filelist that we are
* currently writing (or about to write). */
} state_files;
};
/**
* Create a new ecma119_write_target from the given volume number of the
* given volume set.
*
* \pre \p volnum is less than \p volset-\>volset_size.
* \post For each node in the tree, writer_data has been allocated.
* \post The directory heirarchy has been reorganised to be ecma119-compatible.
*/
struct ecma119_write_target *ecma119_target_new(struct iso_volset *volset,
int volnum,
int level,
int flags);
#define BP(a,b) [(b) - (a) + 1]
struct ecma119_pri_vol_desc
{
uint8_t vol_desc_type BP(1, 1);
uint8_t std_identifier BP(2, 6);
uint8_t vol_desc_version BP(7, 7);
uint8_t unused1 BP(8, 8);
uint8_t system_id BP(9, 40);
uint8_t volume_id BP(41, 72);
uint8_t unused2 BP(73, 80);
uint8_t vol_space_size BP(81, 88);
uint8_t unused3 BP(89, 120);
uint8_t vol_set_size BP(121, 124);
uint8_t vol_seq_number BP(125, 128);
uint8_t block_size BP(129, 132);
uint8_t path_table_size BP(133, 140);
uint8_t l_path_table_pos BP(141, 144);
uint8_t opt_l_path_table_pos BP(145, 148);
uint8_t m_path_table_pos BP(149, 152);
uint8_t opt_m_path_table_pos BP(153, 156);
uint8_t root_dir_record BP(157, 190);
uint8_t vol_set_id BP(191, 318);
uint8_t publisher_id BP(319, 446);
uint8_t data_prep_id BP(447, 574);
uint8_t application_id BP(575, 702);
uint8_t copyright_file_id BP(703, 739);
uint8_t abstract_file_id BP(740, 776);
uint8_t bibliographic_file_id BP(777, 813);
uint8_t vol_creation_time BP(814, 830);
uint8_t vol_modification_time BP(831, 847);
uint8_t vol_expiration_time BP(848, 864);
uint8_t vol_effective_time BP(865, 881);
uint8_t file_structure_version BP(882, 882);
uint8_t reserved1 BP(883, 883);
uint8_t app_use BP(884, 1395);
uint8_t reserved2 BP(1396, 2048);
};
struct ecma119_sup_vol_desc
{
uint8_t vol_desc_type BP(1, 1);
uint8_t std_identifier BP(2, 6);
uint8_t vol_desc_version BP(7, 7);
uint8_t vol_flags BP(8, 8);
uint8_t system_id BP(9, 40);
uint8_t volume_id BP(41, 72);
uint8_t unused2 BP(73, 80);
uint8_t vol_space_size BP(81, 88);
uint8_t esc_sequences BP(89, 120);
uint8_t vol_set_size BP(121, 124);
uint8_t vol_seq_number BP(125, 128);
uint8_t block_size BP(129, 132);
uint8_t path_table_size BP(133, 140);
uint8_t l_path_table_pos BP(141, 144);
uint8_t opt_l_path_table_pos BP(145, 148);
uint8_t m_path_table_pos BP(149, 152);
uint8_t opt_m_path_table_pos BP(153, 156);
uint8_t root_dir_record BP(157, 190);
uint8_t vol_set_id BP(191, 318);
uint8_t publisher_id BP(319, 446);
uint8_t data_prep_id BP(447, 574);
uint8_t application_id BP(575, 702);
uint8_t copyright_file_id BP(703, 739);
uint8_t abstract_file_id BP(740, 776);
uint8_t bibliographic_file_id BP(777, 813);
uint8_t vol_creation_time BP(814, 830);
uint8_t vol_modification_time BP(831, 847);
uint8_t vol_expiration_time BP(848, 864);
uint8_t vol_effective_time BP(865, 881);
uint8_t file_structure_version BP(882, 882);
uint8_t reserved1 BP(883, 883);
uint8_t app_use BP(884, 1395);
uint8_t reserved2 BP(1396, 2048);
};
struct ecma119_vol_desc_terminator
{
uint8_t vol_desc_type BP(1, 1);
uint8_t std_identifier BP(2, 6);
uint8_t vol_desc_version BP(7, 7);
uint8_t reserved BP(8, 2048);
};
struct ecma119_dir_record
{
uint8_t len_dr BP(1, 1);
uint8_t len_xa BP(2, 2);
uint8_t block BP(3, 10);
uint8_t length BP(11, 18);
uint8_t recording_time BP(19, 25);
uint8_t flags BP(26, 26);
uint8_t file_unit_size BP(27, 27);
uint8_t interleave_gap_size BP(28, 28);
uint8_t vol_seq_number BP(29, 32);
uint8_t len_fi BP(33, 33);
uint8_t file_id BP(34, 34); /* 34 to 33+len_fi */
/* padding field (if len_fi is even) */
/* system use (len_dr - len_su + 1 to len_dr) */
};
struct ecma119_path_table_record
{
uint8_t len_di BP(1, 1);
uint8_t len_xa BP(2, 2);
uint8_t block BP(3, 6);
uint8_t parent BP(7, 8);
uint8_t dir_id BP(9, 9); /* 9 to 8+len_di */
/* padding field (if len_di is odd) */
};
/**
* A utility function for writers that want to write their data all at once
* rather than block-by-block. This creates a buffer of size \p size, passes
* it to the given writer, then hands out block-sized chunks.
*/
void
ecma119_start_chunking(struct ecma119_write_target *t,
void (*)(struct ecma119_write_target*, uint8_t*),
off_t size,
uint8_t *buf);
#endif /* LIBISO_ECMA119_H */

View File

@ -1,312 +0,0 @@
/* vim: set noet ts=8 sts=8 sw=8 : */
#include <string.h>
#include <wchar.h>
#include <stdlib.h>
#include <assert.h>
#include "ecma119.h"
#include "ecma119_tree.h"
#include "tree.h"
#include "util.h"
static size_t calc_dirent_len(struct ecma119_tree_node *n)
{
int ret = n->name ? strlen(n->name) + 33 : 34;
if (ret % 2) ret++;
return ret;
}
static struct ecma119_tree_node*
create_dir(struct ecma119_write_target *t,
struct ecma119_tree_node *parent,
struct iso_tree_node *iso)
{
struct ecma119_tree_node *ret;
assert(t && (!parent || parent->type == ECMA119_DIR)
&& iso && S_ISDIR(iso->attrib.st_mode));
ret = calloc(1, sizeof(struct ecma119_tree_node));
ret->name = iso->name ? ((t->iso_level == 1) ? iso_1_dirid(iso->name)
: iso_2_dirid(iso->name))
: NULL;
ret->dirent_len = calc_dirent_len(ret);
ret->iso_self = iso;
ret->target = t;
ret->type = ECMA119_DIR;
ret->parent = ret->dir.real_parent = parent;
ret->dir.depth = parent ? parent->dir.depth + 1 : 1;
ret->dir.nchildren = iso->nchildren;
ret->dir.children = calloc(1, sizeof(void*) * iso->nchildren);
return ret;
}
static struct ecma119_tree_node*
create_file(struct ecma119_write_target *t,
struct ecma119_tree_node *parent,
struct iso_tree_node *iso)
{
struct ecma119_tree_node *ret;
assert(t && iso && parent && parent->type == ECMA119_DIR);
ret = calloc(1, sizeof(struct ecma119_tree_node));
ret->name = iso->name ? ((t->iso_level == 1) ? iso_1_fileid(iso->name)
: iso_2_fileid(iso->name))
: NULL;
ret->dirent_len = calc_dirent_len(ret);
ret->parent = parent;
ret->iso_self = iso;
ret->target = t;
ret->type = ECMA119_FILE;
return ret;
}
static struct ecma119_tree_node*
create_tree(struct ecma119_write_target *t,
struct ecma119_tree_node *parent,
struct iso_tree_node *iso)
{
struct ecma119_tree_node *ret;
size_t i;
assert(t && iso);
ret = (S_ISDIR(iso->attrib.st_mode) ? create_dir : create_file)
(t, parent, iso);
for (i = 0; i < iso->nchildren; i++) {
ret->dir.children[i] = create_tree(t, ret, iso->children[i]);
}
return ret;
}
void
ecma119_tree_free(struct ecma119_tree_node *root)
{
size_t i;
if (root->type == ECMA119_DIR) {
for (i=0; i < root->dir.nchildren; i++) {
ecma119_tree_free(root->dir.children[i]);
}
free(root->dir.children);
}
free(root->name);
free(root);
}
static size_t
max_child_name_len(struct ecma119_tree_node *root)
{
size_t ret = 0, i;
assert(root->type == ECMA119_DIR);
for (i=0; i < root->dir.nchildren; i++) {
size_t len = strlen(root->dir.children[i]->name);
ret = MAX(ret, len);
}
return ret;
}
static void
reparent(struct ecma119_tree_node *child,
struct ecma119_tree_node *parent)
{
int found = 0;
size_t i;
struct ecma119_tree_node *placeholder;
assert(child && parent && parent->type == ECMA119_DIR && child->parent);
/* replace the child in the original parent with a placeholder */
for (i=0; i < child->parent->dir.nchildren; i++) {
if (child->parent->dir.children[i] == child) {
placeholder = create_file(child->target,
child->parent,
child->iso_self);
placeholder->file.real_me = child;
child->parent->dir.children[i] = placeholder;
found = 1;
break;
}
}
assert(found);
/* add the child to its new parent */
child->parent = parent;
parent->dir.nchildren++;
parent->dir.children = realloc( parent->dir.children,
sizeof(void*) * parent->dir.nchildren );
parent->dir.children[parent->dir.nchildren-1] = child;
}
/**
* Reorder the tree, if necessary, to ensure that
* - the depth is at most 8
* - each path length is at most 255 characters
*/
static void
reorder_tree(struct ecma119_tree_node *root,
struct ecma119_tree_node *cur)
{
size_t max_path;
assert(root && cur && cur->type == ECMA119_DIR);
cur->dir.depth = cur->parent ? cur->parent->dir.depth + 1 : 1;
cur->dir.path_len = cur->parent ? cur->parent->dir.path_len
+ strlen(cur->name) : 0;
max_path = cur->dir.path_len + cur->dir.depth + max_child_name_len(cur);
if (cur->dir.depth > 8 || max_path > 255) {
reparent(cur, root);
/* we are appended to the root's children now, so there is no
* need to recurse (the root will hit us again) */
} else {
size_t i;
for (i=0; i < cur->dir.nchildren; i++) {
if (cur->dir.children[i]->type == ECMA119_DIR)
reorder_tree(root, cur->dir.children[i]);
}
}
}
static int
cmp_node(const void *f1, const void *f2)
{
struct ecma119_tree_node *f = *((struct ecma119_tree_node**)f1);
struct ecma119_tree_node *g = *((struct ecma119_tree_node**)f2);
return strcmp(f->name, g->name);
}
static void
sort_tree(struct ecma119_tree_node *root)
{
size_t i;
assert(root && root->type == ECMA119_DIR);
qsort(root->dir.children, root->dir.nchildren, sizeof(void*), cmp_node);
for (i=0; i < root->dir.nchildren; i++) {
if (root->dir.children[i]->type == ECMA119_DIR)
sort_tree(root->dir.children[i]);
}
}
/**
* Change num_change characters of the given filename in order to ensure the
* name is unique. If the name is short enough (depending on the ISO level),
* we can append the characters instead of changing them.
*
* \p seq_num is the index of this file in the sequence of identical filenames.
*
* For example, seq_num=3, num_change=2, name="HELLOTHERE.TXT" changes name to
* "HELLOTHE03.TXT"
*/
static void
mangle_name(char **name, int num_change, int level, int seq_num)
{
char *dot = strrchr(*name, '.');
char *semi = strrchr(*name, ';');
size_t len = strlen(*name);
char base[len+1], ext[len+1];
char fmt[12];
size_t baselen, extlen;
if (num_change >= len) {
return;
}
strncpy(base, *name, len+1);
if (dot) {
base[dot - *name] = '\0';
strncpy(ext, dot+1, len+1);
if (semi) {
ext[semi - dot - 1] = '\0';
}
} else {
base[len-2] = '\0';
ext[0] = '\0';
}
baselen = strlen(base);
extlen = strlen(ext);
if (level == 1 && baselen + num_change > 8) {
base[8 - num_change] = '\0';
} else if (level != 1 && baselen + extlen + num_change > 30) {
base[30 - extlen - num_change] = '\0';
}
sprintf(fmt, "%%s%%0%1dd.%%s;1", num_change);
*name = realloc(*name, baselen + extlen + num_change + 4);
sprintf(*name, fmt, base, seq_num, ext);
}
static void
mangle_all(struct ecma119_tree_node *dir)
{
size_t i, j, k;
struct ecma119_dir_info d = dir->dir;
size_t n_change;
int changed;
assert(dir->type == ECMA119_DIR);
do {
changed = 0;
for (i=0; i < d.nchildren; i++) {
/* find the number of consecutive equal names */
j = 1;
while ( i+j < d.nchildren &&
!strcmp(d.children[i]->name,
d.children[i+j]->name) )
j++;
if (j == 1) continue;
/* mangle the names */
changed = 1;
n_change = j / 10 + 1;
for (k=0; k < j; k++) {
mangle_name(&(d.children[i+k]->name),
n_change,
dir->target->iso_level,
k);
d.children[i+k]->dirent_len =
calc_dirent_len(d.children[i+k]);
}
/* skip ahead by the number of mangled names */
i += j - 1;
}
} while (changed);
for (i=0; i < d.nchildren; i++) {
if (d.children[i]->type == ECMA119_DIR)
mangle_all(d.children[i]);
}
}
struct ecma119_tree_node*
ecma119_tree_create(struct ecma119_write_target *t,
struct iso_tree_node *iso_root)
{
t->root = create_tree(t, NULL, iso_root);
reorder_tree(t->root, t->root);
sort_tree(t->root);
mangle_all(t->root);
return t->root;
}
void
ecma119_tree_print(struct ecma119_tree_node *root, int spaces)
{
size_t i;
char sp[spaces+1];
memset(sp, ' ', spaces);
sp[spaces] = '\0';
printf("%s%s\n", sp, root->name);
if (root->type == ECMA119_DIR)
for (i=0; i < root->dir.nchildren; i++)
ecma119_tree_print(root->dir.children[i], spaces+2);
}

View File

@ -1,95 +0,0 @@
/* vim: set noet ts=8 sts=8 sw=8 : */
/**
* \file ecma119_tree.h
*
* Declarations for creating, modifying and printing filesystem trees that
* are compatible with ecma119.
*/
#ifndef LIBISO_ECMA119_TREE_H
#define LIBISO_ECMA119_TREE_H
struct ecma119_write_target;
enum {
ECMA119_FILE,
ECMA119_DIR
};
struct ecma119_dir_info {
struct susp_info self_susp; /**< susp entries for "." */
struct susp_info parent_susp; /**< susp entries for ".." */
size_t len; /**< sum of the lengths of children's
* Directory Records (including SU) */
size_t CE_len; /**< sum of the lengths of children's
* SUSP CE areas */
int depth;
size_t path_len; /**< The length of a path up to, and
* including, this directory. This
* cannot exceed 255. */
size_t nchildren;
struct ecma119_tree_node **children;
struct ecma119_tree_node *real_parent;
/**< The parent before relocation */
};
struct ecma119_file_info
{
struct ecma119_tree_node *real_me;
/**< If this is non-NULL, the file is
* a placeholder for a relocated
* directory and this field points to
* that relocated directory.
*/
};
/**
* A node for a tree containing all the information necessary for writing
* an ISO9660 volume.
*/
struct ecma119_tree_node
{
char *name; /**< in ASCII, conforming to the
* current ISO level. */
size_t dirent_len; /**< Length of the directory record,
* not including SU. */
size_t block;
struct ecma119_tree_node *parent;
struct iso_tree_node *iso_self;
struct ecma119_write_target *target;
struct susp_info susp;
int type; /**< file or directory */
/* union {*/
struct ecma119_dir_info dir;
struct ecma119_file_info file;
/* };*/
};
/**
* Create a new ecma119_tree that corresponds to the tree represented by
* \p iso_root.
*/
struct ecma119_tree_node*
ecma119_tree_create(struct ecma119_write_target *target,
struct iso_tree_node *iso_root);
/**
* Free an ecma119 tree.
*/
void
ecma119_tree_free(struct ecma119_tree_node *root);
/**
* Print an ecma119 tree.
*/
void
ecma119_tree_print(struct ecma119_tree_node *root, int spaces);
#endif /* LIBISO_ECMA119_TREE_H */

View File

@ -1,42 +0,0 @@
#include "hash.h"
#include "exclude.h"
static struct iso_hash_node *table[HASH_NODES]={0,};
static int num=0;
void
iso_exclude_add_path(const char *path)
{
if (!path)
return;
num += iso_hash_insert(table, path);
}
void
iso_exclude_remove_path(const char *path)
{
if (!num || !path)
return;
num -= iso_hash_remove(table, path);
}
void
iso_exclude_empty(void)
{
if (!num)
return;
iso_hash_empty(table);
num=0;
}
int
iso_exclude_lookup(const char *path)
{
if (!num || !path)
return 0;
return iso_hash_lookup(table, path);
}

View File

@ -1,12 +0,0 @@
#ifndef ISO_EXCLUDE_H
#define ISO_EXCLUDE_H
/**
* Add a path to ignore when adding a directory recursively.
*
* \param path The path, on the local filesystem, of the file.
*/
int
iso_exclude_lookup(const char *path);
#endif /* ISO_EXCLUDE */

View File

@ -1,158 +0,0 @@
#include <stdlib.h>
#include <string.h>
#include "hash.h"
static unsigned int
iso_hash_path(const char *path)
{
unsigned int hash_num=0;
const char *c;
c=path;
while(*c)
hash_num = (hash_num << 15) + (hash_num << 3) + (hash_num >> 3) + *c++;
return hash_num % HASH_NODES;
}
int
iso_hash_lookup(struct iso_hash_node **table, const char *path)
{
struct iso_hash_node *node;
unsigned int hash_num;
hash_num = iso_hash_path(path);
node=table[hash_num];
if (!node)
return 0;
if (!strcmp(path, node->path))
return 1;
while (node->next) {
node=node->next;
if (!strcmp(path, node->path))
return 1;
}
return 0;
}
static struct iso_hash_node*
iso_hash_node_new (const char *path)
{
struct iso_hash_node *node;
/*create an element to be inserted in the hash table */
node=malloc(sizeof(struct iso_hash_node));
node->path=strdup(path);
node->next=NULL;
return node;
}
int
iso_hash_insert(struct iso_hash_node **table, const char *path)
{
struct iso_hash_node *node;
unsigned int hash_num;
/* find the hash number */
hash_num = iso_hash_path(path);
/* insert it */
node = table[hash_num];
/* unfortunately, we can't safely consider that a path
* won't be twice in the hash table so make sure it
* doesn't already exists */
if (!node) {
table[hash_num]=iso_hash_node_new(path);
return 1;
}
/* if it's already in, we don't do anything */
if (!strcmp(path, node->path))
return 0;
while (node->next) {
node = node->next;
/* if it's already in, we don't do anything */
if (!strcmp (path, node->path))
return 0;
}
node->next = iso_hash_node_new(path);
return 1;
}
static void
iso_hash_node_free(struct iso_hash_node *node)
{
free(node->path);
free(node);
}
int
iso_hash_remove(struct iso_hash_node **table, const char *path)
{
unsigned int hash_num;
struct iso_hash_node *node;
hash_num = iso_hash_path(path);
node=table[hash_num];
if (!node)
return 0;
if (!strcmp(path, node->path)) {
table[hash_num]=node->next;
iso_hash_node_free(node);
return 1;
}
while (node->next) {
struct iso_hash_node *prev;
prev = node;
node = node->next;
if (!strcmp (path, node->path)) {
prev->next=node->next;
iso_hash_node_free(node);
return 1;
}
}
return 0;
}
void
iso_hash_empty(struct iso_hash_node **table)
{
int i;
for (i=0; i < HASH_NODES; i++) {
struct iso_hash_node *node;
node=table[i];
if (!node)
continue;
table[i]=NULL;
do {
struct iso_hash_node *next;
next=node->next;
iso_hash_node_free(node);
node=next;
} while (node);
}
}

Some files were not shown because too many files have changed in this diff Show More