Compare commits

..

249 Commits

Author SHA1 Message Date
4175023fcd Documented last minute changes 2008-04-08 11:47:17 +00:00
80c16a3b48 Switched from configure.ac versioning to libburn.h versioning 2008-04-08 11:17:34 +00:00
e1cc10b42e Documented changes and release timestamp 2008-04-08 09:08:39 +00:00
0b23bfc764 Updated cdrskin tarball generator 2008-04-08 09:06:10 +00:00
f3bef987ed Made number transition and activated development documentation 2008-04-08 09:04:03 +00:00
94069733e9 Created 0.4.4 branch 2008-04-07 20:04:23 +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
70 changed files with 12880 additions and 1395 deletions

View File

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

View File

@ -3,3 +3,4 @@ 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-2007 Mario Danic, Thomas Schmitt
Copyright (C) 2006-2008 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

View File

@ -101,10 +101,14 @@ test_structest_CPPFLAGS = -Ilibburn
test_structest_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
test_structest_SOURCES = test/structest.c
## cdrskin construction site - ts A60816 - A70720
## cdrskin construction site - ts A60816 - A80408
cdrskin_cdrskin_CPPFLAGS = -Ilibburn
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_0_3_8
cdrskin_cdrskin_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_0_4_4
# 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
##
## Open questions: how to compute $timestamp and express -DX="$timestamp"

120
README
View File

@ -1,25 +1,25 @@
------------------------------------------------------------------------------
libburnia.pykix.org
libburnia-project.org
------------------------------------------------------------------------------
This all is under GPL.
(See GPL reference, our clarification and commitment at the end of this text)
------------------------------------------------------------------------------
libburnia.pykix.org
libburnia-project.org
By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
Copyright (C) 2006-2007 Mario Danic, Thomas Schmitt
Copyright (C) 2006-2008 Mario Danic, Thomas Schmitt
Still containing parts of
Libburn. By Derek Foreman <derek@signalmarketing.com> and
Ben Jansens <xor@orodu.net>
Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
These parts are to be replaced by own code of above libburnia.pykix.org
copyright holders and then libburnia.pykix.org is to be their sole copyright.
These parts are to be replaced by own code of above libburnia-project.org
copyright holders and then libburnia-project.org is to be their sole copyright.
This is done to achieve the right to issue the clarification and the
commitment as written at the end of this text.
The rights and merits of the Libburn-copyright holders Derek Foreman and
Ben Jansens will be duely respected.
This libburnia.pykix.org toplevel README (C) 2006-2007 Thomas Schmitt
This libburnia-project.org toplevel README (C) 2006-2008 Thomas Schmitt
------------------------------------------------------------------------------
Build and Installation
@ -27,33 +27,39 @@ This libburnia.pykix.org toplevel README (C) 2006-2007 Thomas Schmitt
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://libburnia-svn.pykix.org/libburn/trunk libburn_pykix
go into directory libburn_pykix and apply autotools by
svn co http://svn.libburnia-project.org/libburn/trunk libburn
go into directory libburn and apply autotools by
./bootstrap
Alternatively you may unpack a release tarball for which you do not need
autotools installed.
To build a libburnia.pykix.org subproject it should be sufficient to go
into its toplevel directory (here: "libburn_pykix") and execute
./configure
To build a libburnia-project.org subproject it should be sufficient to go
into its toplevel directory (here: "libburn") and execute
./configure --prefix=/usr
make
To make the libraries accessible for running resp. developing applications
and to install the cdrecord compatibility binary cdrskin, do:
make install
The other half of the project, libisofs, is hosted in the libburnia SVN, too:
svn co http://libburnia-svn.pykix.org/libisofs/trunk libisofs_pykix
See README file there.
An important part of the project, libisofs, is hosted in a bzr repository at
launchpad.net :
bzr branch lp:libisofs
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.pykix.org
Overview of libburnia-project.org
libburnia.pykix.org is an open-source software project for reading, mastering
libburnia-project.org is an open-source software project for reading, mastering
and writing optical discs.
For now this means only CD media and all single layer DVD media except DVD+R.
@ -67,29 +73,39 @@ we would need : login on a development machine resp. a live OS on CD or DVD,
advise from a system person about the equivalent of Linux sg or FreeBSD CAM,
volunteers for testing of realistic use cases.
We have a workable code base for burning CD and most single layer DVD.
The burn API is quite comprehensively documented and can be used to build a
presentable application.
We have a functional binary which emulates parts of cdrecord in order to
prove that usability, and in order to allow you to explore libburnia's scope
by help of existing cdrecord frontends.
We have a well tested code base for burning data and audio CDs and many DVD
types. The burn API is quite comprehensively documented and can be used to
build a presentable application.
We have a functional binary which emulates the core use cases of cdrecord in
order to prove that usability, and in order to allow you to explore libburn's
scope by help of existing cdrecord frontends.
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).
/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 media via libburn.
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. Additionally it
provides libburn's DVD capabilities, where only -sao is compatible
@ -97,14 +113,34 @@ The project components (list subject to growth, hopefully):
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 and man cdrskin/cdrskin.1 for more.
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 deletion, renaming, and attribute
changing.
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).
------------------------------------------------------------------------------
@ -204,6 +240,30 @@ Project history as far as known to me:
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.
------------------------------------------------------------------------------

View File

@ -1,84 +1,36 @@
------------------------------------------------------------------------------
libburnia.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:
libburnia.pykix.org
By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
Copyright (C) 2006-2007 Mario Danic, Thomas Schmitt
libburnia.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
libburnia.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 libburnia.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.3.8.tar.gz
Copyright (C) 2006-2007 Thomas Schmitt
http://scdbackup.sourceforge.net/cdrskin-0.4.4.pl00.tar.gz
Copyright (C) 2006-2008 Thomas Schmitt, provided under GPL version 2.
------------------------------------------------------------------------------
On top of libburn there is implemented cdrskin 0.3.8, 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 only supported on Linux with kernels >= 2.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.3.8.tar.gz, take it to a directory of your choice and do:
Obtain cdrskin-0.4.4.pl00.tar.gz, take it to a directory of your choice and do:
tar xzf cdrskin-0.3.8.tar.gz
cd cdrskin-0.3.8
tar xzf cdrskin-0.4.4.pl00.tar.gz
cd cdrskin-0.4.4
Or obtain a libburnia.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.3.8 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.
@ -92,11 +44,21 @@ Version identification and help texts available afterwards:
cdrskin/cdrskin -help
man cdrskin/cdrskin.1
Install (eventually as superuser) cdrskin to a directory where it can be found:
If cdrskin was already installed by a previous version, or by "make install"
in the course of this installation, then find out where:
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.
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
@ -113,6 +75,10 @@ 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
@ -137,9 +103,21 @@ So full and insecure enabling of both for everybody would look like
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
@ -174,7 +152,7 @@ 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
Write multi-session to the same CD , DVD-R[W] or DVD+R
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 -tao 2.iso
cdrskin dev=/dev/hdc padsize=300k -multi -tao 3.iso
@ -201,44 +179,32 @@ See below "Audio CD" for specifications.
-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/sr1"
Set usage of cdrskin with appropriate options rather than cdrecord :
export SCDBACKUP_CDRECORD="cdrskin -v -v"
Run a backup :
scdbackup_home
Restrictions
Many cdrecord options are still unsupported.
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.
DVD support is restricted to single layer DVD for now. Double layer media
are implemented but untested.
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.)
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.
@ -249,94 +215,6 @@ Many thanks to Andy Polyakov for his dvd+rw-tools
which provide me with examples and pointers into MMC specs for DVD writing.
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 device file /dev/s[rg]N 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 (resp. its /dev/sr*), "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/sr1 \
dev_translation=+ATA:1,0,0+/dev/sr1 \
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/sr1 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/sr1
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.
Startup Files
If not --no_rc is the first argument then cdrskin attempts on startup to read
@ -352,8 +230,6 @@ 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_at=0
@ -395,24 +271,19 @@ Speed is counted in DVD units (i.e. 1x = 1,385,000 bytes/second). Currently
there is no difference between -sao and -tao. If ever, then -tao will be the
mode which preserves the current behavior.
For these media, -msinfo alone would not be enough to perform appending of an
ISO filesystem. The filesystem driver will need a hint to find the start of the
most recent session. For example put an ISO filesystem at address 1 GB:
mkisofs -C 0,524288 ... | \
cdrskin dev=/dev/sr0 -v fs=32m -eject speed=4 write_start_address=524288s -
The superuser may then do:
mount -t iso9660 -o ro,sbsector=524288 /dev/sr0 /mnt
Note: On my linux-2.4.21-215 mount works only with sbsector <= 337920 (660 MiB)
To extend a filesystem already existing at address 0
mkisofs -C 0,524288 -M /dev/sr0 ... | cdrskin dev=/dev/sr0 ...
Record the number 524288 for usage as first number with -C at the next
extension:
mkisofs -C 524288,1000000 ... | cdrskin write_start_address=1000000s ...
Program growisofs can append to an ISO filesystem on DVD+RW by additionally
manipulating the first session. cdrskin does not want to get involved so deep
into the format of the burned data. Be advised to use growisofs for the
task of maintaining extendable ISO-Filesystems on DVD+RW.
manipulating the first session. Meanwhile cdrskin can do the same.
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
@ -428,7 +299,7 @@ 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
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.)
@ -437,7 +308,7 @@ 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.)
(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
@ -470,10 +341,28 @@ 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 and DVD+R/DL
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 ia reading drive might show some delay while switching
between both media layers.
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.
------------------------------------------------------------------------------
@ -494,12 +383,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 implied the need to reboot the
system because of drives gnawing endlessly on ill media. Permanent hardware
damage did not occur in 1.5 years of development.
------------------------------------------------------------------------------
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
@ -510,6 +423,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-2008 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

@ -38,7 +38,7 @@ original="./libburn_svn_release.tgz"
# My changes are in $changes , mainly in $changes/cdrskin
changes="./libburn-release"
skin_release="0.3.8"
skin_release="0.4.4"
patch_level=".pl00"
skin_rev="$skin_release""$patch_level"
@ -58,7 +58,8 @@ 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}-x86-suse9_0"
bintarget_dynamic="cdrskin_${skin_rev}-amd64-suse10_2"
bintarget_static="$bintarget_dynamic"-static
if test -d "$changes"
@ -154,6 +155,10 @@ do
fi
done
# Remove libcevap
rm -rf "$target"/libcevap
# Remove unwanted SVN stuff (TODO: avoid downloading it)
for i in "$target"/.svn "$target"/*/.svn
do

View File

@ -24,9 +24,9 @@ set -x
# The top level directory in the SVN snapshot is named
intermediate="./libburn_pykix"
# libburn source used: http://libburnia.pykix.org
# libburn source used: http://libburnia-project.org
# Downloaded by:
# $ svn co http://libburnia-svn.pykix.org/libburn/tags/... $intermediate
# $ 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 $intermediate
original="./libburn_svn.tgz"
@ -38,7 +38,7 @@ original="./libburn_svn.tgz"
# My changes are in $changes , mainly in $changes/cdrskin
changes="./libburn-develop"
skin_release="0.3.9"
skin_release="0.4.5"
patch_level=""
skin_rev="$skin_release""$patch_level"
@ -58,7 +58,7 @@ 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"
@ -143,6 +143,9 @@ 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
@ -222,6 +225,8 @@ tar czf "$cdrskin_tarball" "$target"
"$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" ..
)
@ -234,7 +239,7 @@ rm -rf "$target"
./"$bintarget_dynamic" -version
./"$bintarget_static" -version
ls -l "$cdrskin_tarball"
ls -l "$bintarget_dynamic"
ls -l "$bintarget_dynamic"*
ls -l "$bintarget_static"
ls -l $(basename "$man_page_html")

View File

@ -79,6 +79,7 @@ struct CdrfifO {
/* 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 */
@ -162,6 +163,7 @@ int Cdrfifo_new(struct CdrfifO **ff, int source_fd, int dest_fd,
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;
@ -222,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);
@ -400,6 +404,14 @@ int Cdrfifo_get_iso_fs_size(struct CdrfifO *o, double *size_in_bytes, int flag)
}
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.
*/
@ -882,19 +894,24 @@ int Cdrfifo_fill(struct CdrfifO *o, int size, int flag)
}
#ifndef Cdrfifo_standalonE
{ int Scan_for_iso_size(unsigned char data[2048], double *size_in_bytes,
if(fill>=32*2048) {
int Scan_for_iso_size(unsigned char data[2048], double *size_in_bytes,
int flag);
int i;
int bs= 16*2048;
double size;
/* try to obtain an ISO-9660 file system size */
for(i= 0; i<32*2048 && i+2048<=fill; i+=2048) {
ret= Scan_for_iso_size((unsigned char *) (o->buffer+i), &size, 0);
if(ret<=0)
continue;
/* 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;
break;
}
}
#endif

View File

@ -123,6 +123,16 @@ int Cdrfifo_get_cdr_counters(struct CdrfifO *o,
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
data and the destination fd for readiness to accept some. If so, a small

View File

@ -2,7 +2,7 @@
.\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1)
.TH CDRSKIN 1 "July 19, 2007"
.TH CDRSKIN 1 "September 26, 2007"
.\" Please adjust this date whenever revising the manpage.
.\"
.\" Some roff macros, for reference:
@ -16,8 +16,8 @@
.\" .sp <n> insert n+1 empty lines
.\" for manpage-specific macros, see man(7)
.SH NAME
cdrskin \- burns preformatted data to CD-R[W], DVD-R[W], DVD+R[W], DVD-RAM
via libburn.
cdrskin \- burns preformatted data to CD-R[W], DVD-R[W], DVD+R[W], DVD+R/DL,
DVD-RAM via libburn.
.SH SYNOPSIS
.B cdrskin
.RI [ options | track_source_addresses ]
@ -31,7 +31,7 @@ via libburn.
\fBcdrskin\fP is a program that provides some of cdrecord's options
in a compatible way for CD media. With DVD it has its own ways.
You do not need to be superuser for its daily usage.
.PP
.SS
.B Overview of features:
.br
Blanking of CD-RW and DVD-RW.
@ -44,16 +44,20 @@ or in Session at Once mode for seamless tracks.
.br
Multi session on CD (follow-up sessions in TAO only)
.br
or on DVD-R[W] (in Incremental mode) or on DVD+R.
or on DVD-R[W] (in Incremental mode) or on DVD+R[/DL].
.br
Single session on DVD-RW or DVD-R (Disk-at-once)
Single session on DVD-RW or DVD-R (Disk-at-once).
.br
or on overwriteable DVD+RW, DVD-RW, DVD-RAM.
Single session or emulated ISO-9660 multi-session
.br
on overwriteable DVD+RW, DVD-RW, DVD-RAM,
.br
or on data file or block device.
.br
Bus scan, burnfree, speed options, retrieving media info, padding, fifo.
.br
See section EXAMPLES at the end of this text.
.PP
.SS
.B General information paragraphs:
.br
Track recording model
@ -67,7 +71,9 @@ Sequentially Recordable DVD Media
Overwriteable DVD Media
.br
Drive preparation and addressing
.PP
.br
Emulated drives
.SS
.B Track recording model:
.br
The input-output entities which get processed are called tracks.
@ -109,9 +115,22 @@ Another type of data track content are archive formats which originally
have been developed for magnetic tapes. Only formats which mark a detectable
end-of-archive in their data are suitable, though. Well tested are
the archivers afio and star. Not suitable seems GNU tar.
.PP
.SS
.B Write mode selection:
.br
In general there are two approaches for writing media:
.br
A permissive mode depicted by option
.B -tao
which needs no predicted track size and allows to make use of
eventual multi-session capabilities.
.br
A more restrictive mode
.B -sao
(alias -dao) which usually demands a predictable track size and is not
necessarily capable of multi-session. It may have advantages for some
readers resp. players of the recorded tracks.
.br
If none of the options -dao, -tao or -sao is given then the program will
try to choose a write mode which matches the defined recording job,
the capabilities of the drive and the state of the present media.
@ -119,7 +138,7 @@ the capabilities of the drive and the state of the present media.
So the mentioning of write modes in the following paragraphs and in the
examples is not so much a demand that the user shall choose one explicitely,
but rather an illustration of what to expect with particular media types.
.PP
.SS
.B Recordable CD Media:
.br
CD-R can be initially written only once and eventually extended until they
@ -128,15 +147,11 @@ read-only. Closing is done automatically unless option
.B -multi
is given which keeps the media appendable.
.br
There are two write modes,
.B -tao
and
.B -sao .
.br
-tao allows to use track source of unpredictable length (like stdin) and allows
to write further sessions to appendable media. -sao produces audio sessions
with seamless tracks but needs predicted track sizes and cannot append sessions
to media.
Write mode
-tao allows to use track sources of unpredictable length (like stdin) and
allows to write further sessions to appendable media.
-sao produces audio sessions with seamless tracks but needs predicted track
sizes and cannot append sessions to media.
.br
CD-RW media can be blanked to make them re-usable for another
round of overwriting. Usually
@ -145,10 +160,10 @@ is the appropriate option.
Blanking damages the previous content but does not
make it completely unreadable. It is no effective privacy precaution.
Multiple cycles of blanking and overwriting with random numbers might be.
.PP
.SS
.B Sequentially Recordable DVD Media:
.br
Currently DVD-RW, DVD-R and DVD+R can be used for the Sequential recording
Currently DVD-RW, DVD-R and DVD+R[/DL] can be used for the Sequential recording
model.
.br
DVD-RW must be in state "Sequential Recording".
@ -183,22 +198,35 @@ unpredicted length and to keep media appendable by option
The only restriction towards CD-R[W] is the lack of support for -audio tracks.
Multiple tracks per session are permissible.
.br
The write modes for DVD+R resemble those with DVD-R except that with DVD+R
The write modes for DVD+R[/DL] resemble those with DVD-R except that with +R
each track gets wrapped in an own session. There is no -dummy writing with
DVD+R.
DVD+R[/DL].
.br
Quite deliberately write mode -sao insists in the tradition of a predicted
track size and blank media, whereas -tao writes the tracks open ended and
allows appendable media.
.PP
.br
.B Note:
Option -multi might make DVD media unreadable in some DVD-ROM drives.
Best reader compatibility is achieved without it
(i.e. by single session media).
.SS
.B Overwriteable DVD Media:
.br
Currently types DVD+RW, DVD-RW and DVD-RAM can be overwritten via cdrskin.
.br
DVD+RW and DVD-RAM media get treated as blank media regardless wether they
hold data or not. They need no special initial formatting.
Options -audio and -multi are not allowed. Only one track is allowed.
-toc does not return information about the media content.
DVD+RW and DVD-RAM media need no special initial formatting. They offer a
single continuous data area for blockwise random access.
.br
Option -audio is not allowed. Only one track is allowed.
Option -multi cannot mark a recognizeable end of overwriteable media.
Therefore -multi is banned unless ISO-9660 images shall be expandable by help
of option
.B --grow_overwriteable_iso .
Without this option or without an ISO-9660 filesystem image present
on media, -toc does not return information about the media content and
media get treated as blank regardless wether they hold data or not.
.br
Currently there is no difference between -sao and -tao. If ever, then -tao
will be the mode which preserves the current behavior.
.br
@ -211,7 +239,7 @@ can be done by option
Several programs like dvd+rw-format, cdrecord, wodim, or cdrskin
can bring a DVD-RW out of overwriteable state so
that it has to be formatted again. If in doubt, just give it a try.
.PP
.SS
.B Drive preparation and addressing:
.br
The drives, either CD burners or DVD burners, are accessed via addresses which
@ -226,8 +254,10 @@ who is able to get this list without further
precautions.
.br
It is consensus that \fBchmod a+rw /dev/sr0\fP or \fBchmod a+rw /dev/hdc\fP
is less security sensitive than chmod u+s /usr/bin/cdrskin. The risk for the
drive is somewhat higher but the overall system is much less at stake.
is less security sensitive than chmod u+s,a+x /usr/bin/cdrskin. The risk for
the drive is somewhat higher but the overall system is much less at stake.
Consider to restrict rw-access to a single group which bundles the users who
are allowed to use the burner drive (like group "floppy").
.br
.PP
If you only got one CD capable drive then you may leave out cdrskin option
@ -245,6 +275,40 @@ Further are accepted on Linux: links to libburn-suitable device files,
device files which have the same major and minor device number,
and device files which have the same SCSI address parameters (e.g. /dev/sg0).
.br
.SS
.B Emulated drives:
.br
Option
.B --allow_emulated_drives
enables addressing of pseudo-drives
which get emulated on top of filesystem objects. Regular data files and
block devices result in pseudo-drives which behave much like DVD-RAM.
If the given address does not exist yet but its directory exists, then
it gets created as regular file.
Other file types like character devices or pipes result in pseudo-drives
which behave much like blank DVD-R.
The target file address is given after prefix "stdio:".
.br
E.g.: dev=stdio:/tmp/my_pseudo_drive
.br
Addresses of the form "stdio:/dev/fd/<number>" are treated special. The
number is read literally and used as open file descriptor. With
dev="stdio:/dev/fd/1" the normal standard output of the program is
redirected to stderr and the stream data of a burn run will appear on stdout.
.br
Not good for terminals ! Redirect it.
.br
Pseudo-drives allow -dummy. Their reply with --tell_media_space can be utopic.
-dummy burn runs touch the file but do not modify its data content.
.br
Note: --allow_emulated_drives is restricted to stdio:/dev/null if cdrskin
is run by the
.B superuser
or if it has changed user identity via the
.B setuid
bit of its access permissions. The ban for the superuser can be lifted by a
skillfully created file. See section FILES below.
.br
.SH OPTIONS
.TP
.BI \-\-help
@ -252,6 +316,11 @@ Show non-cdrecord compatible options.
.TP
.BI \-help
Show cdrecord compatible options.
.br
Note that some of the help texts are quite wrong - for cdrecord as well as
for cdrskin (e.g. -format, blank=, -load). They are, nevertheless, traditional
indicators for the availability of the listed options. Some frontend programs
make decisions after reading them.
.TP
.BI \-version
Print cdrskin id line, compatibility lure line, libburn version, cdrskin
@ -286,11 +355,11 @@ Print this list of blanking types.
.TP
all
Blank an entire CD-RW or an unformatted DVD-RW.
(See also --prodvd_cli_compatible)
(See also --prodvd_cli_compatible, --grow_overwriteable_iso)
.TP
fast
Minimally blank an entire CD-RW or blank an unformatted DVD-RW.
(See also --prodvd_cli_compatible)
(See also --prodvd_cli_compatible, --grow_overwriteable_iso)
.TP
format_overwrite
Format a DVD-RW to "Restricted Overwrite". The user should bring some patience.
@ -330,7 +399,7 @@ Incremental Streaming (-tao).
.RE
.TP
.BI \-checkdrive
Retrieve some info about the addressed drive.
Retrieve some info about the addressed drive and then exit.
Exits with non-zero value if the drive cannot be found and opened.
.TP
.BI \-dao
@ -368,7 +437,7 @@ Try to perform the drive operations without actually affecting the inserted
media. There is no warranty that this will work with a particular combination
of drive, media, and write mode. Blanking is prevented reliably, though.
To avoid inadverted real burning, -dummy refuses burn runs on anything but
CD-R[W] and DVD-R[W].
CD-R[W], DVD-R[W], or emulated stdio-drives.
.TP
.BI \-eject
Eject the disc after work is done.
@ -388,6 +457,9 @@ that drive and media will not simulate the write mode but will write for real.
.B Caution:
Use this only when in urgent need.
.TP
.BI \-format
Same as blank=format_overwrite_full -force but restricted to DVD+RW.
.TP
.BI fs= size
Set the fifo size to the given value. The value may have appended letters which
multiply the preceding number:
@ -407,6 +479,19 @@ option fifo_start_at=size.
.BI gracetime= seconds
Set the grace time before starting to write. (Default is 0)
.TP
.BI -immed
Equivalent to:
.br
modesty_on_drive=1:min_percent=75:max_percent=95
.br
The name of this cdrecord option stems from the "Immed" bit which can make some
long running drive commands asynchronous and thus eases the load on some
wiring hardware types. Regardless of option -immed, cdrskin uses asynchronous
commands where possible and appropriate.
.TP
.BI -inq
Print the identification of the drive and then exit.
.TP
.BI -isosize
The next track following this option will try to obtain its source size from
the header information out of the first few blocks of the source data.
@ -423,6 +508,18 @@ This option can be performed on track sources which are regular files or block
devices. For the first track of the session it can be performed on any type
of source if there is a fifo of at least 64 kiB. See option fs= .
.TP
.BI -load
Load the media and exit. Exit value is 0 if any kind of media was found, non
zero else. Note: Option -eject will unload the media even if -load is given.
.TP
.BI -lock
Like option -load but leave the drive's eject button disabled if there is any
media found and not option -eject is given.
.br
Use program "eject" or cdrskin -eject to get the tray out of the drive.
Runs of programs like cdrecord, growisofs, wodim, cdrskin will not be hampered
and normally enable the drive's eject button when they are done.
.TP
.BI minbuf= percentage
Equivalent to:
.br
@ -446,6 +543,9 @@ The result string shall be used as argument of option -C with said programs.
It gives the start address of the most recent session and the predicted
start address of the next session to be appended. The string is empty if
the most recent session was not written with option -multi.
.br
To have a chance for working on overwriteable media, this option has to be
accompanied by option --grow_overwriteable_iso.
.TP
.BI \-multi
This option keeps the CD or unformatted DVD-R[W] appendable after the current
@ -454,9 +554,8 @@ Without it the disc gets closed and may not be written any more - unless it
is a -RW and gets blanked which causes loss of its content.
.br
The following sessions can only be written in -tao mode. -multi is prohibited
with overwriteable DVD media and with DVD-R[W] DAO write mode.
Option --prodvd_cli_compatible eventually makes -multi tolerable but cannot
make it work.
with DVD-R[W] DAO write mode. Option --prodvd_cli_compatible eventually makes
-multi tolerable but cannot make it work.
.br
In order to have all filesystem content accessible, the eventual ISO-9660
filesystem of a follow-up
@ -466,6 +565,15 @@ which can be retrieved by cdrskin option -msinfo.
.br
To retrieve an archive file which was written as follow-up session,
you may use option -toc to learn about the "lba" of the desired track number.
This lba is the address of the 2048 byte block where the archive begins.
.br
With overwriteable DVD media, -multi cannot mark the end of the session.
So when adding a new session this end has to be determined from the payload.
Currently only ISO-9660 filesystems can be used that way. See option
.B \--grow_overwriteable_iso
for lifting the ban on -multi.
.br
Note: -multi might make DVD media unreadable in some DVD-ROM drives.
.TP
.BI \-nopad
Do not add trailing zeros to the data stream. Nevertheless, since there seems
@ -490,7 +598,7 @@ One should use it only if inavoidable.
.TP
.BI \-sao
Write CD in Session At Once mode, a sequential DVD-R[W] in Disc-at-once
(DAO) mode, or a DVD+R.
(DAO) mode, or a DVD+R[/DL].
.br
With CD this mode is able to put several audio tracks on media without
producing audible gaps between them.
@ -498,8 +606,8 @@ producing audible gaps between them.
With DVD-R[W] this mode can only write a single track.
No -multi is allowed with DVD-R[W] -sao.
.br
-sao is permissible with overwriteable DVD and with DVD+R but actually only
imposes restrictions without providing known advantages.
-sao is permissible with overwriteable DVD and with DVD+R[/DL] but actually
only imposes restrictions without providing known advantages.
.br
-sao can only be used for tracks of fixely predicted size. This implies that
track arguments which depict stdin or named pipes need to be preceeded by
@ -527,7 +635,7 @@ It is not an error to set a speed higher than is suitable for drive
and media. One should stay within a realistic speed range, though.
Special speed settings are:
.br
0 = minimal speed , -1 = maximal speed (default).
0 = minimal speed , -1 = maximal speed (default), text "any" = like -1.
.TP
.BI \-swab
Announce that the raw audio data source of subsequent tracks is byte swapped
@ -539,7 +647,7 @@ suffix ".wav".
.TP
.BI \-tao
Write CD in Track At Once (TAO) mode, sequential DVD-R[W] in Incremental
Streaming mode, or DVD+R without traditional -sao restrictions.
Streaming mode, or DVD+R[/DL] without traditional -sao restrictions.
This mode also applies pro-forma to overwriteable DVD media.
.br
Mode -tao can be used with track sources of unpredictable size, like standard
@ -591,6 +699,23 @@ some extra lines to be put out with info retrieval options.
Level 2 additionally reports about option settings derived from arguments or
startup files. Level 3 is for debugging and useful mainly in conjunction with
somebody who had a look into the program sourcecode.
.TP
.BI \-waiti
Wait until input data is available at stdin or EOF occurs at stdin.
Only then begin to access any drives.
.br
One should use this if cdrskin is working at the end of a pipe where the
feeder process reads from the drive before it starts writing its output into
cdrskin. Example:
.br
mkisofs ... -C 0,12800 -M /dev/sr0 | \\
.br
cdrskin dev=/dev/sr0 ... -waiti -
.br
This option works even if stdin is not among the track sources. If no process
is piping in, then the Enter key of your terminal will act as trigger for
cdrskin. Note that this input line will not be consumed by cdrskin if stdin
is not among the track sources. It will end up as shell command, usually.
.PP
Alphabetical list of options which are genuine to cdrskin and intended for
normal use:
@ -601,6 +726,10 @@ drive for the loaded media. By default, such an adjustment is only made with
pseudo-speeds 0 and -1 whereas speed settings > 0 are sent unchanged to the
drive which will then choose an appropriate speed on its own.
.TP
.BI \--allow_emulated_drives
Enable drive addresses of the form dev=stdio:<path>. See above, paragraph
"Drive preparation and addressing".
.TP
.BI \--allow_setuid
Disable the loud warning about insecure discrepance between login user and
effective user which indicates application of chmod u+s to the program binary.
@ -642,6 +771,59 @@ Number dev='Devicefile' rw-Permissions : 'Vendor' 'Model'
Number and Devicefile can both be used with option dev=, but number is
volatile (numbering changes if drives become busy).
.TP
.BI direct_write_amount= size
Do not write a session with tracks but rather make an appropriate number of
direct write operations with no preparations. Flushing the drive buffer will
be the only finalization. It is advised to eject the media afterwards because
the write operations circumvent the usual system i/o with its caches and
buffers. By ejecting, those invalid memory copies get surely discarded.
.br
Only few media can be written this way: DVD-RAM, RVD+RW and overwriteable
DVD-RW. Writing is restricted to the already formatted area of the media.
.br
Writing starts at byte 0 of the media or at the address given by option
.B write_start_address= .
Only the first track source is used as input for the write operations.
The fifo (fs=) is disabled.
.br
Parameter
.B size
controls the amount of data to be written. Size 0 means that the track source
shall be used up until EOF. In this case, the last write transaction gets
padded up to the necessary size by zeros. Size -1 revokes direct writing
and switches back to normal session oriented writing.
.br
Both, write_start_address and direct_write_amount size must be aligned to a
media dependend transaction size. With DVD-RAM and DVD+RW this is 2k, with
overwriteable DVD-RW it is 32k.
.TP
.BI fallback_program= command
Set a command name to be executed if cdrskin encounters a known cdrecord
option which it does not yet support. If a non-empty command is given with
fallback_program=, and if no essential options are given which are specific
to cdrskin, then cdrskin will delegate the job to said command.
.br
The natural commands to be given are cdrecord or wodim but one may well submit
the address of an own program.
.br
The fallback programm will get all arguments of cdrskin which do not match
the shell patterns --?* or *_*=* . This eventually suppresses path names of
track sources which happen to match those patterns. The options from the
startup files are not handed to the fallback program.
.br
Fallback program execution is disabled if cdrskin is run setuid and not
option --allow_setuid is given. In general, the drive's device files and the
involved programs should be set up so that each program runs under its advised
conditions. (E.g. cdrskin as member of group floppy, cdrecord setuid root.)
.br
Two alias names for cdrskin are predefined with default fallback programs:
.br
.B unicord
implies fallback_program=cdrecord
.br
.B codim
implies fallback_program=wodim
.TP
.BI fifo_start_at= size
Do not wait for full fifo but start burning as soon as the given number
of bytes is read. This option may be helpful to bring the average throughput
@ -652,6 +834,46 @@ the software protection against buffer underun is as weak as the size of
fifo_start_at= . So it is best if the drive offers hardware protection which
is enabled automatically if not driveropts=noburnfree is given.
.TP
.BI \--grow_overwriteable_iso
Enable emulation of multi-session writing on overwriteable media which
contain an ISO-9660 filesystem. This emulation is learned from growisofs -M
but adapted to the usage model of
.br
.B cdrskin -msinfo
.br
.B mkisofs -C -M | cdrskin -waiti [-multi] -
.br
--grow_overwriteable_iso does not hamper the use of true multi-session media.
I.e. it is possible to use the same cdrskin options with both kinds of media
and to achieve similar results if ISO-9660 filesystem images are to be written.
This option implies option -isosize and therefore demands that the track
source is a ISO-9660 filesystem image.
.br
With overwriteable media and no option blank=fast|all present it expands an
eventual ISO-9660 filesystem on media. It is assumed that this image's inner
size description points to the end of the valuable data.
Overwriteable media with a recognizeable ISO-9660 size will be regarded as
appendable rather than as blank. I.e. options -msinfo and -toc will work.
-toc will always show a single session with its size increasing with
every added mkisofs image.
.br
If not overriden by option write_start_address=, the track with the new image
will be placed behind the end of the old one. One may use option
assert_write_lba= to make sure that media state and mkisofs job do match.
.br
--grow_overwriteable_iso causes option blank=fast|all to invalidate an
eventual ISO-9660 image by altering the first few bytes of block 16 on
overwriteable media.
Option -multi is tolerated in order not to hamper true multi-session media.
.br
An equivalent of growisofs -Z for overwriteable media is:
.br
.B mkisofs | cdrskin --grow_overwriteable_iso blank=fast [-multi] -
.br
With multi-session DVD, blank=fast will act like dvd+rw-format -blank=full .
.br
growisofs -dvd-compat is roughly equivalent to cdrskin without option -multi.
.TP
.BI \--list_ignored_options
List all ignored cdrecord options. The "-" options cannot be used as addresses
of track sources. No track source address may begin with a text equal to an
@ -729,7 +951,7 @@ tested. Currently this applies to :
.br
Profile 0015h , DVD-R/DL Sequential (will not allow -multi).
.br
Profile 002Bh , DVD+R/DL.
Profile 0043h , BD-RE.
.br
If you really test such media, then please report the outcome on
libburn-hackers@pykix.org
@ -796,9 +1018,12 @@ This option overrides option -multi. It will not fill up media if option -sao
is given with CD media.
.br
.B Caution:
This option might increase read compatibility with DVD-ROM drives but
with some DVD recorders and media types it might also fail to produce readable
media at all. "Your mileage may vary".
With multi-session media this option might increase readatibility on DVD-ROM
drives but with some DVD recorders and media types it might also fail to
produce readable media at all. "Your mileage may vary".
.br
You can expect the best possible read compatibility if you do not use -multi at
all.
.TP
.BI grab_drive_and_wait= seconds
Open the addressed drive, wait the given number of seconds, release the drive,
@ -906,7 +1131,7 @@ cdrskin -v dev=0,1,0 fs=32m speed=8 \\
.br
-tao padsize=300k -
.SS
.B Write multi-session to the same CD, DVD-R[W] or DVD+R:
.B Write multi-session to the same CD, DVD-R[W] or DVD+R[/DL]:
.br
cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 1.iso
.br
@ -937,6 +1162,9 @@ cdrskin -v dev=ATA:1,0,0 speed=48 -sao \\
track1.wav track2.au -audio -swab track3.raw
.br
.SH FILES
.SS
Startup files:
.br
If not --no_rc is given as the first argument then cdrskin attempts on
startup to read the arguments from the following files:
.PP
@ -954,23 +1182,32 @@ The files are read in the sequence given above, but none of them is
required for cdrskin to function properly. Each readable line is treated
as one single argument. No extra blanks.
A first character '#' marks a comment, empty lines are ignored.
.SS
.B Example content of a startup file:
.br
Example content of a startup file:
.br
# This is the default device
.br
dev=0,1,0
.br
# To accomodate to remnant cdrskin-0.2.2 addresses
.br
dev_translation=+1,0,0+0,1,0
.br
# Some more options
.br
fifo_start_at=0
.br
fs=16m
.br
.SS
Disabling superuser safety precautions:
The superuser is normally banned from using any other emulated drive but
/dev/null. This ban can be lifted by the existence of file
.PP
.B /root/cdrskin_permissions/allow_emulated_drives
.PP
where the directory must be owned by the superuser and must not offer
w-permissions for group or others.
.br
Warning: Superusers must take care not to spoil their hard disk via its raw
block device (like stdio:/dev/hda or stdio:/dev/sd0).
.SH SEE ALSO
.TP
Formatting data track sources for cdrskin:

File diff suppressed because it is too large Load Diff

View File

@ -2,7 +2,7 @@
<HEAD>
<META NAME="description" CONTENT="cdrskin, a limited cdrecord compatibility wrapper for libburn">
<META NAME="keywords" CONTENT="cdrskin, libburn, libburnia, burn, CD, DVD, linux, recording, burning, CD-R, CD-RW, DVD-R, DVD-RW, DVD+RW, DVD+R, cdrecord, compatible, scdbackup">
<META NAME="keywords" CONTENT="cdrskin, libburn, libburnia, burn, CD, DVD, linux, recording, burning, CD-R, CD-RW, DVD-R, DVD-RW, DVD+RW, DVD+R, DVD+R/DL, DVD-RAM, cdrecord, compatible, scdbackup">
<META NAME="robots" CONTENT="follow">
<TITLE>cdrskin homepage english</TITLE>
</HEAD>
@ -24,8 +24,8 @@
<P>
<H2>Purpose:</H2>
Burns preformatted data to CD and single layer DVD media:<BR>
CD-R, DVD-R, DVD+R, CD-RW, DVD-RW, DVD-RAM, DVD+RW
Burns preformatted data to CD and DVD media:<BR>
CD-R, DVD-R, DVD+R, DVD+R/DL, CD-RW, DVD-RW, DVD-RAM, DVD+RW
</P>
<P>
@ -34,7 +34,7 @@ CD-R, DVD-R, DVD+R, CD-RW, DVD-RW, DVD-RAM, DVD+RW
<P>
<H2>Hardware requirements:</H2>
A CD/DVD recorder suitable for
<A HREF="http://libburnia.pykix.org">libburnia.pykix.org</A> <BR>
<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).
<BR>
@ -43,7 +43,7 @@ and to MMC-5 for DVD).
<P>
<H2>Software requirements :</H2>
<DL>
<DT>Linux kernel 2.4 or higher</DT>
<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>libpthread</DT>
@ -56,8 +56,9 @@ and to MMC-5 for DVD).
GPL software included:<BR>
</H2>
<DL>
<DT>libburn-0.3.8</DT>
<DD>(by Derek Foreman, Ben Jansens, and team of libburnia.pykix.org)</DD>
<DT>libburn-0.4.4</DT>
<DD>(founded by Derek Foreman and Ben Jansens,
furthered by team of libburnia-project.org)</DD>
<DD>transfers data to CD and DVD</DD>
</DL>
</P>
@ -124,7 +125,7 @@ as listed by option --devices.</DT>
<DD><KBD>&nbsp;&nbsp;cdrskin -v dev=0,1,0 fs=32m speed=8 \</KBD></DD>
<DD><KBD>&nbsp;&nbsp;-tao padsize=300k -</KBD></DD>
<DT>Write several sessions to the same CD, DVD-R[W] or DVD+R:</DT>
<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 -tao 1.iso</KBD>
</DD>
<DD>$<KBD>&nbsp;cdrskin dev=/dev/hdc -v padsize=300k -multi -tao 2.iso</KBD>
@ -165,8 +166,16 @@ man cdrecord</A></KBD></DD>
this "don't bother Joerg" demand.)
</DD>
</DL>
<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 double layer DVD media.
Testers wanted who are willing to risk some double layer DVD-R media
or to do experiments on BD-RE.
</P>
@ -175,29 +184,34 @@ Testers wanted who are willing to risk some double layer DVD media.
<P>
<DL>
<DT>Download as source code (see README):</DT>
<DD><A HREF="cdrskin-0.3.8.pl00.tar.gz">cdrskin-0.3.8.pl00.tar.gz</A>
(615 KB).
<DD><A HREF="cdrskin-0.4.4.pl00.tar.gz">cdrskin-0.4.4.pl00.tar.gz</A>
(715 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 for 0.4.4 and 0.4.5
<DD>&nbsp;</DD>
<DT>Download as single x86 binaries (untar and move to /usr/bin/cdrskin):</DT>
<DD><A HREF="cdrskin_0.3.8.pl00-x86-suse9_0.tar.gz">
cdrskin_0.3.8.pl00-x86-suse9_0.tar.gz</A>, (90 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.3.8.pl00-x86-suse9_0-static.tar.gz">
cdrskin_0.3.8.pl00-x86-suse9_0-static.tar.gz</A>, (290 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>
-->
</DL>
<DL><DT>Documentation:</DT>
<DD><A HREF="README_cdrskin">README</A> an introduction</DD>
@ -220,18 +234,14 @@ cdrskin_0.3.8.pl00-x86-suse9_0-static.tar.gz</A>, (290 KB), -static compiled,
<HR>
<P>
Enhancements towards previous stable version cdrskin-0.3.4:
Enhancements towards previous stable version cdrskin-0.4.2:
<UL>
<LI>Now able to cope with the peculiarities of Linux 2.4 USB</LI>
<LI>Refusal to perform -dummy runs on media which cannot simulate burning</LI>
<LI>Precautions against using the burner drive as track source</LI>
<LI>New option modesty_on_drive= may help with hda -> hdb burns</LI>
<LI>New option minbuf= , cdrecord compatible frontend of modesty_on_drive=</LI>
<LI>New option --adjust_speed_to_drive</LI>
<LI>Support for DVD+R/DL media is now official</LI>
<LI>Experimental code for BD-RE with --allow_untested_media</LI>
</UL>
<!--
Bug fixes towards cdrskin-0.3.8.pl00:
Bug fixes towards cdrskin-0.4.2.pl00:
<UL>
<LI>none yet</LI>
</UL>
@ -243,23 +253,25 @@ Enhancements towards previous stable version cdrskin-0.3.4:
<P>
<DL>
<DT><H3>Development snapshot, version 0.3.9 :</H3></DT>
<DD>Enhancements towards stable version 0.3.8.pl00:
<DT><H3>Development snapshot, version 0.4.5 :</H3></DT>
<DD>Enhancements towards stable version 0.4.4.pl00:
<UL>
<!--
-->
<LI>none yet</LI>
</UL>
</DD>
<DD>&nbsp;</DD>
<DD><A HREF="README_cdrskin_devel">README 0.3.9</A>
<DD><A HREF="cdrskin__help_devel">cdrskin_0.3.9 --help</A></DD>
<DD><A HREF="cdrskin_help_devel">cdrskin_0.3.9 -help</A></DD>
<DD><A HREF="man_1_cdrskin_devel.html">man cdrskin (as of 0.3.9)</A></DD>
<DD><A HREF="README_cdrskin_devel">README 0.4.5</A>
<DD><A HREF="cdrskin__help_devel">cdrskin_0.4.5 --help</A></DD>
<DD><A HREF="cdrskin_help_devel">cdrskin_0.4.5 -help</A></DD>
<DD><A HREF="man_1_cdrskin_devel.html">man cdrskin (as of 0.4.5)</A></DD>
<DD>&nbsp;</DD>
<DT>Maintainers of cdrskin unstable packages please use SVN of
<A HREF="http://libburnia.pykix.org"> libburnia.pykix.org</A></DT>
<DD>Download: <KBD><B>svn co http://libburnia-svn.pykix.org/libburn/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.
@ -267,22 +279,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
<A HREF="README_cdrskin_devel">upcoming README</A> ):
</DD>
<DD>
<A HREF="cdrskin-0.3.9.tar.gz">cdrskin-0.3.9.tar.gz</A>
(615 KB).
<A HREF="cdrskin-0.4.5.tar.gz">cdrskin-0.4.5.tar.gz</A>
(715 KB).
</DD>
<!-- This is not offered any more for 0.4.4 and 0.4.5
<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.3.9-x86-suse9_0.tar.gz">
cdrskin_0.3.9-x86-suse9_0.tar.gz</A>, (90 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.3.9-x86-suse9_0-static.tar.gz">
cdrskin_0.3.9-x86-suse9_0-static.tar.gz</A>, (290 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>
@ -330,6 +349,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">
@ -384,6 +405,8 @@ and try again.
</DL>
</P>
-->
<HR>
<A NAME="cdrecord">
@ -443,14 +466,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 "2007.07.20.120001"
#define Cdrskin_timestamP "2008.04.08.100001"

File diff suppressed because it is too large Load Diff

View File

@ -1,13 +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=
largefile_opts="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1"
libvers="-DCdrskin_libburn_0_3_8"
libvers="-DCdrskin_libburn_0_4_4"
cleanup_src_or_obj="libburn/cleanup.o"
libdax_msgs_o="libburn/libdax_msgs.o"
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
@ -33,15 +33,15 @@ do
libdax_audioxtr_o=
libdax_msgs_o="libburn/message.o"
cleanup_src_or_obj="-DCleanup_has_no_libburn_os_H cdrskin/cleanup.c"
elif test "$i" = "-libburn_0_3_8"
elif test "$i" = "-libburn_0_4_4"
then
libvers="-DCdrskin_libburn_0_3_8"
libvers="-DCdrskin_libburn_0_4_4"
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_3_9"
libvers="-DCdrskin_libburn_0_4_5"
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
libdax_msgs_o="libburn/libdax_msgs.o"
cleanup_src_or_obj="libburn/cleanup.o"
@ -68,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"
@ -79,7 +76,7 @@ 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_3_8 set macro to match libburn-0.3.8."
echo " -libburn_0_4_4 set macro to match libburn-0.4.4."
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."
@ -87,8 +84,7 @@ do
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"
@ -133,6 +129,7 @@ then
\
libburn/sg.o \
libburn/write.o \
libburn/read.o \
$libdax_audioxtr_o \
$libdax_msgs_o \
\

View File

@ -16,7 +16,7 @@ manpage="cdrskin"
raw_html=$(pwd)/"cdrskin/raw_man_1_cdrskin.html"
htmlpage=$(pwd)/"cdrskin/man_1_cdrskin.html"
if test -r "$manpage"
if test -r "$man_dir"/"$manpage".1
then
dummy=dummy
else
@ -45,17 +45,19 @@ then
-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/^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/^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/^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/and for all others\.<\/td><\/table>/and for all others.<\/td><\/table> <BR><HR><FONT SIZE=-1><CENTER>(HTML generated from '"$manpage"'.1 on '"$(date)"' by '$(basename "$0")' )<\/CENTER><\/FONT>/' \
-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"

View File

@ -10,21 +10,20 @@ Schilling's cdrtools. cdrskin strives to be a second source for the services
traditionally provided by cdrecord. Currently it does CD-R and CD-RW this way.
Overwriteable media DVD-RAM, DVD+RW and DVD-RW are handled differently than
with cdrecord-ProDVD in order to offer TAO-like single track recording.
Sequential DVD-R[W] and DVD+R are handled like CD-R[W] with TAO and
Sequential DVD-R[W], DVD+R, DVD+R/DL are handled like CD-R[W] with TAO and
multi-session. Additionally cdrskin offers cdrecord-ProDVD-like mode DAO
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 [http://libburnia.pykix.org/browser/libburn/trunk/cdrskin/README?format=txt 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: http://libburnia-api.pykix.org
About libburn API for burning CD and DVD: http://api.libburnia-project.org
--------------------------------------------------------------------------
For dual layer DVD types and for appending sessions to ISO filesystems on
DVD other than DVD-RW, DVD-R, DVD+R see the advise to use dvd+rw-tools at
For yet unsupported media types see the advice to use dvd+rw-tools at
the end of this text.
--------------------------------------------------------------------------
@ -80,12 +79,45 @@ controls drive accessability by rw-permissions of the drive rather than
by x-permission of the burn binary. To be usable with cdrskin, the drive
has to offer both, r- and w-permission.
--------------------------------------------------------------------------
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 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.
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
@ -107,7 +139,8 @@ 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.
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".
@ -117,6 +150,13 @@ 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 and DVD+RW 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
@ -228,10 +268,10 @@ for an illustrated example with K3b 0.10 .
DVD advise:
For burning of DVD media other than DVD-RAM, DVD+RW, DVD+R, DVD-RW, DVD-R,
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 also do dual layer and even BD discs.
For burning of DVD media other than DVD-RAM, DVD+RW, DVD+R, DVD+R/DL,
DVD-RW, DVD-R, 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
@ -239,19 +279,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).
--------------------------------------------------------------------------
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 for growable ISO filesystems on DVD-RAM or DVD+RW growisofs is the only
choice, currently.
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 and
even regular disk files or block devices other than CD/DVD writers.
This is enabled by option --grow_overwriteable_iso.
cdrskin can offer DVD multi-session only with sequential DVD-R[W] and with
DVD+R.
Associated options blank=, -multi, -msinfo and -toc are available in this case.
Thus sequential DVD-RW behave much like large CD-RW with possibly more than 99
tracks.
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.3.8], [http://libburnia.pykix.org])
AC_INIT([libburn], [0.4.4], [http://libburnia-project.org])
AC_PREREQ([2.50])
dnl AC_CONFIG_HEADER([config.h])
@ -7,35 +7,104 @@ AC_CANONICAL_TARGET
AM_INIT_AUTOMAKE([subdir-objects])
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 - A80126 :
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
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=3
BURN_MICRO_VERSION=8
BURN_INTERFACE_AGE=0
BURN_BINARY_AGE=0
BURN_MINOR_VERSION=4
BURN_MICRO_VERSION=4
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=4
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 A80127
dnl This is the release version libburn-0.4.4 = libburn.so.4.9.0
dnl ### This is the development version after libburn-0.4.4 = libburn.so.4.9.0
dnl ### LT_CURRENT++, LT_AGE++ has not yet happened.
dnl
dnl SONAME = 13 - 9 = 4 . Library name = libburn.so.4.9.0
LT_CURRENT=13
LT_REVISION=0
LT_AGE=9
LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
AC_SUBST(LT_RELEASE)
@ -44,6 +113,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

View File

@ -7,10 +7,10 @@
Libburnia is an open-source project for reading, mastering and writing
optical discs.
For now this means CD-R, CD-RW, DVD-RAM, DVD+RW, DVD+R, DVD-RW, DVD-R.
For now this means CD-R, CD-RW, DVD-RAM, DVD+RW, DVD+R, DVD+R/DL, DVD-RW, DVD-R.
Not supported yet are dual layer media, HD-DVD, BD (blue ray). Testers for
dual layer DVD+/-R are wanted, though.
Not supported yet are DVD-R/DL, HD-DVD, BD (blue ray). Testers for
BD and DVD-R/DL are wanted, though.
The project comprises of several more or less interdependent parts which
together strive to be a usable foundation for application development.
@ -22,13 +22,18 @@ we would need : login on a development machine resp. a live OS on CD or DVD,
advise from a system person about the equivalent of Linux sg or FreeBSD CAM,
volunteers for testing of realistic use cases.
We have a workable code base for burning data and audio CDs and many DVD types.
The burn API is quite comprehensively documented and can be used to build a
presentable application.
We have a well tested code base for burning data and audio CDs and many DVD
types. The burn API is quite comprehensively documented and can be used to
build a presentable application.
We have a functional binary which emulates the core use cases of cdrecord in
order to prove that usability, and in order to allow you to explore libburn's
scope by help of existing cdrecord frontends.
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.
@subsection components The project components (list subject to growth, hopefully):
- libburn is the library by which preformatted data get onto optical media.
@ -43,6 +48,11 @@ scope by help of existing cdrecord frontends.
ISO 9660 disk image. This may then be brought to CD via libburn.
libisofs is to be the foundation of our upcoming mkisofs emulation.
- libisoburn is an add-on to libburn and libisofs which coordinates both and
also allows to grow ISO-9660 filesystem images on multi-session
media as well as on overwriteable media via the same API.
All media peculiarities are handled automatically.
- cdrskin is a limited cdrecord compatibility wrapper for libburn.
cdrecord is a powerful GPL'ed burn program included in Joerg
Schilling's cdrtools. cdrskin strives to be a second source for
@ -54,13 +64,32 @@ scope by help of existing cdrecord frontends.
runs, though.
See cdrskin/README for more.
- xorriso is an application of all three libraries which creates, loads,
manipulates and writes ISO 9660 filesystem images with
Rock Ridge extensions. Manipulation is not only adding or
overwriting of files but also deletion, renaming, and attribute
changing.
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 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).
@section using Using the libraries
@ -89,7 +118,7 @@ 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 .
(see: libburn/libburn.h) as provided on http://libburnia-project.org .
It can list the available devices, can blank a CD-RW or DVD-RW and
can burn to recordable CD and recordable single layer DVD.

View File

@ -1,4 +1,4 @@
libburnia.pykix.org Optical Media Rotisserie Recipes as of February 2007
libburnia-project.org Optical Media Rotisserie Recipes as of August 2007
Content:
- TAO Multi-Session CD Cookbook (CD-R, CD-RW)
@ -18,7 +18,7 @@ by reading libburn/* from http://icculus.org/burn
and by experiments with drives NEC ND-4570A, LG GSA-4082B, LITE-ON LTR48125S
which used in part code from http://icculus.org/burn.
For libburnia.pykix.org by Thomas Schmitt <scdbackup@gmx.net>
For libburnia-project.org by Thomas Schmitt <scdbackup@gmx.net>
-------------------------------------------------------------------------------
@ -215,7 +215,7 @@ backed by reading mmc5r03c.pdf from http://www.t10.org/ftp/t10/drafts/mmc5/
and by experiments with drives NEC ND-4570A, LG GSA-4082B, LITE-ON LTR48125S
which used in part code from http://icculus.org/burn.
For libburnia.pykix.org by Thomas Schmitt <scdbackup@gmx.net>
For libburnia-project.org by Thomas Schmitt <scdbackup@gmx.net>
-------------------------------------------------------------------------------
@ -405,7 +405,7 @@ Inspired by Andy Polyakov's http://fy.chalmers.se/~appro/linux/DVD+RW/tools ,
backed by reading mmc5r03c.pdf from http://www.t10.org/ftp/t10/drafts/mmc5/
and by experiments with drives NEC ND-4570A and LG GSA-4082B.
For libburnia.pykix.org by Thomas Schmitt <scdbackup@gmx.net>
For libburnia-project.org by Thomas Schmitt <scdbackup@gmx.net>
-------------------------------------------------------------------------------
@ -680,7 +680,7 @@ Inspired by Andy Polyakov's http://fy.chalmers.se/~appro/linux/DVD+RW/tools ,
backed by reading mmc5r03c.pdf from http://www.t10.org/ftp/t10/drafts/mmc5/
and by experiments with drives NEC ND-4570A and LG GSA-4082B.
For libburnia.pykix.org by Thomas Schmitt <scdbackup@gmx.net>
For libburnia-project.org by Thomas Schmitt <scdbackup@gmx.net>
-------------------------------------------------------------------------------
@ -990,15 +990,12 @@ close session if multi-session is demanded.
-------------------------------------------------------------------------------
-------------------------------------------------------------------------------
INCOMPLETE YET
DVD+R Cookbook
-------------------------------------------------------------------------------
Inspired by reading mmc5r03c.pdf from http://www.t10.org/ftp/t10/drafts/mmc5/
backed by Andy Polyakov's http://fy.chalmers.se/~appro/linux/DVD+RW/tools ,
For libburnia.pykix.org by Thomas Schmitt <scdbackup@gmx.net>
For libburnia-project.org by Thomas Schmitt <scdbackup@gmx.net>
-------------------------------------------------------------------------------
@ -1088,8 +1085,19 @@ closed by Close Function 101b rather than 010b. This finalizes the media
"with minimal radius".
(mmc5r03c.pdf 6.3.3.4.4)
Note: growisofs has code for that gesture but explicitly avoids to use it.
Instead it recommends to fill up the media with zeros.
Note: growisofs has code for that gesture but explicitly avoids to use it, if
the media was appendable before writing began. Instead it recommends to fill
up the media with zeros. This gesture nevertheless caused error replies from
the drives in my own experiments.
The reason given by Andy Polyakov is that some DVD-ROM drives get mislead by
the lead-out information of (formerly) appendable media unless the media is
fully written.
(http://fy.chalmers.se/~appro/linux/DVD+RW/ , "Compatibility: caveat lector")
Own experiments showed no such problems with PC attached PATA DVD-ROM drives.
For best DVD-ROM compatibility one should avoid appendable media at all
by closing them already after the first session.
-------------------------------------------------------------------------------
Hearsay about DVD+R/DL (Dual Layer) :

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,5 +1,25 @@
/* -*- 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"
@ -7,9 +27,12 @@
#include "options.h"
#include "async.h"
#include "init.h"
#include "file.h"
#include "back_hacks.h"
#include <pthread.h>
#include <sys/types.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
@ -53,6 +76,12 @@ struct write_opts
struct burn_disc *disc;
};
struct fifo_opts
{
struct burn_source *source;
int flag;
};
struct w_list
{
@ -67,10 +96,12 @@ struct w_list
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)
{
@ -86,6 +117,11 @@ static void add_worker(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->drive = d;
@ -96,26 +132,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;
}
@ -130,7 +205,12 @@ 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);
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;
}
@ -165,12 +245,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;
@ -211,9 +292,6 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
{
struct erase_opts o;
/* A70103 : will be set to 0 by burn_disc_erase_sync() */
drive->cancel = 1;
/* ts A61006 */
/* a ssert(drive); */
/* a ssert(!SCAN_GOING()); */
@ -233,12 +311,17 @@ 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 &&
@ -247,6 +330,8 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
(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,
@ -287,6 +372,14 @@ void burn_disc_format(struct burn_drive *drive, off_t size, int flag)
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 */
@ -320,7 +413,13 @@ void burn_disc_format(struct burn_drive *drive, off_t size, int flag)
static void *write_disc_worker_func(struct w_list *w)
{
struct burn_drive *d = w->u.write.drive;
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
*/
@ -334,17 +433,6 @@ void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
{
struct write_opts o;
char reasons[BURN_REASONS_LEN+80];
#ifndef Libburn_precheck_write_ruleS
int i, j, mode, mixed_mode = 0;
#endif
/* 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;
/* ts A61006 */
/* a ssert(!SCAN_GOING()); */
@ -357,8 +445,24 @@ 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,
@ -372,48 +476,13 @@ void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
strcpy(reasons, "Write job parameters are unsuitable:\n");
if (burn_precheck_write(opts, disc, reasons + strlen(reasons), 1)
== BURN_WRITE_NONE) {
#ifndef Libburn_precheck_write_ruleS
libdax_msgs_submit(libdax_messenger,
opts->drive->global_index, 0x00020139,
LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
reasons, 0, 0);
#else
libdax_msgs_submit(libdax_messenger,
opts->drive->global_index, 0x00020139,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
reasons, 0, 0);
return;
#endif /* Libburn_precheck_write_ruleS */
}
#ifndef Libburn_precheck_write_ruleS
/* <<< covered burn_precheck_write() */
/* ts A61009 : obsolete Assert in sector_headers() */
if (! burn_disc_write_is_ok(opts, disc, 0)) /* issues own msgs */
return;
/* <<< covered burn_precheck_write() */
/* ts A70122 : libburn SAO code mishandles mode changes */
for (i = 0; i < disc->sessions; i++) {
if (disc->session[i]->tracks <= 0)
continue;
mode = disc->session[i]->track[0]->mode;
for (j = 1; j < disc->session[i]->tracks; j++)
if (mode != disc->session[i]->track[j]->mode)
mixed_mode = 1;
}
if (mixed_mode && opts->write_type == BURN_WRITE_SAO) {
libdax_msgs_submit(libdax_messenger,
opts->drive->global_index, 0x00020133,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Cannot mix data and audio in SAO mode", 0, 0);
return;
}
#endif /* ! Libburn_precheck_write_ruleS */
opts->drive->cancel = 0; /* End of the return = failure area */
o.drive = opts->drive;
@ -425,6 +494,40 @@ void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
add_worker(opts->drive, (WorkerFunc) write_disc_worker_func, &o);
}
static void *fifo_worker_func(struct w_list *w)
{
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(NULL, (WorkerFunc) fifo_worker_func, &o);
fs->is_started = 1;
return 1;
}
#ifdef Libburn_has_burn_async_join_alL
/* ts A71019 : never used */
void burn_async_join_all(void)
{
void *ret;
@ -432,3 +535,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,10 @@
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);
#endif /* BURN__ASYNC_H */

File diff suppressed because it is too large Load Diff

View File

@ -43,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);
@ -52,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);
@ -111,4 +114,15 @@ 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);
#endif /* __DRIVE */

View File

@ -2,12 +2,21 @@
#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 "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 */
@ -93,14 +102,14 @@ 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);
@ -108,15 +117,30 @@ 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)
/* 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;
@ -139,14 +163,23 @@ struct burn_source *burn_fd_source_new(int datafd, int subfd, off_t size)
if (datafd == -1)
return NULL;
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();
/* ts A70825 */
if (src == NULL) {
free((char *) fs);
return NULL;
}
src->read = file_read;
if(subfd != -1)
src->read = file_read_sub;
src->read_sub = file_read_sub;
src->get_size = file_size;
src->set_size = file_set_size;
src->free_data = file_free;
@ -154,3 +187,356 @@ struct burn_source *burn_fd_source_new(int datafd, int subfd, off_t size)
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;
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;
fs->thread_pid = getpid();
fs->thread_pid_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;
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_pid = 0;
fs->thread_pid_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;
}

View File

@ -5,13 +5,58 @@
struct burn_source_file
{
char magic[4];
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;
int thread_pid;
int thread_pid_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
@ -53,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"
@ -61,6 +66,10 @@ 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 */
@ -107,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" */
@ -200,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)
@ -226,40 +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)
{
#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 Not_yeT
pthread_t thread_id;
#ifdef Libburn_new_thread_signal_handleR
/* >>> need better handling of self-induced SIGs
like SIGSEGV or SIGFPE.
Like bonking the control thread if it did not show up
after a short while.
*/
ret = burn_drive_find_by_thread_pid(&d, getpid());
if (ret > 0 && d->busy == BURN_DRIVE_WRITING) {
/* This is an active writer thread */
/* >>> if this is a non-fatal signal : return -2 */
#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
thread_id = pthread_self();
/* >>> find thread_id in worker list of async.c */
/* >>> if owning a drive : mark idle and canceled
(can't do anything more) */
d->sync_cache(d);
usleep(1000000); /* calm down */
/* >>> perform a more qualified end of burn process */;
/* forward signal to control thread */
if (abort_control_pid>1)
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);
}
/* >>> ??? end thread */;
#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 /* ! Not_yeT */
#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);
@ -267,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);
}
@ -289,8 +388,10 @@ 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;
}
@ -300,3 +401,16 @@ 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 */

View File

@ -251,7 +251,15 @@ enum burn_drive_status
/* ts A61223 */
/** The drive is formatting media */
BURN_DRIVE_FORMATTING
BURN_DRIVE_FORMATTING,
/* ts A70822 */
/** The drive is busy in synchronous read (if you see this then it
has been interrupted) */
BURN_DRIVE_READING_SYNC,
/** The drive is busy in synchronous write (if you see this then it
has been interrupted) */
BURN_DRIVE_WRITING_SYNC
};
@ -291,7 +299,7 @@ struct burn_toc_entry
/** Track start time frames for normal tracks */
unsigned char pframe;
/* Indicates wether extension data are valid and eventually override
/* Indicates whether extension data are valid and eventually override
older elements in this structure:
bit0= DVD extension is valid
*/
@ -310,39 +318,158 @@ struct burn_toc_entry
};
/** Data source for tracks */
/** Data source interface for tracks.
This allows to use arbitrary program code as provider of track input data.
Objects compliant to this interface are either provided by the application
or by API calls of libburn: burn_fd_source_new() , burn_file_source_new(),
and burn_fifo_source_new().
The API calls allow to use any file object as data source. Consider to feed
an eventual custom data stream asynchronously into a pipe(2) and to let
libburn handle the rest.
In this case the following rule applies:
Call burn_source_free() exactly once for every source obtained from
libburn API. You MUST NOT otherwise use or manipulate its components.
In general, burn_source objects can be freed as soon as they are attached
to track objects. The track objects will keep them alive and dispose them
when they are no longer needed. With a fifo burn_source it makes sense to
keep the own reference for inquiring its state while burning is in
progress.
---
The following description of burn_source applies only to application
implemented burn_source objects. You need not to know it for API provided
ones.
If you really implement an own passive data producer by this interface,
then beware: it can do anything and it can spoil everything.
In this case the functions (*read), (*get_size), (*set_size), (*free_data)
MUST be implemented by the application and attached to the object at
creation time.
Function (*read_sub) is allowed to be NULL or it MUST be implemented and
attached.
burn_source.refcount MUST be handled properly: If not exactly as many
references are freed as have been obtained, then either memory leaks or
corrupted memory are the consequence.
All objects which are referred to by *data must be kept existent until
(*free_data) is called via burn_source_free() by the last referer.
*/
struct burn_source {
/** Reference count for the data source. Should be 1 when a new source
is created. Increment it to take a reference for yourself. Use
burn_source_free to destroy your reference to it. */
/** Reference count for the data source. MUST be 1 when a new source
is created and thus the first reference is handed out. Increment
it to take more references for yourself. Use burn_source_free()
to destroy your references to it. */
int refcount;
/** Read data from the source */
int (*read)(struct burn_source *,
unsigned char *buffer,
int size);
/** Read subchannel data from the source (NULL if lib generated) */
int (*read_sub)(struct burn_source *,
unsigned char *buffer,
int size);
/** Read data from the source. Semantics like with read(2), but MUST
either deliver the full buffer as defined by size or MUST deliver
EOF (return 0) or failure (return -1) at this call or at the
next following call. I.e. the only incomplete buffer may be the
last one from that source.
libburn will read a single sector by each call to (*read).
The size of a sector depends on BURN_MODE_*. The known range is
2048 to 2352.
/** Get the size of the source's data */
IMPORTANT:
If this function pointer is NULL, then the struct burn_source is of
version >= 1 and the job of .(*read)() is done by .(*read_xt)().
See below, member .version.
*/
int (*read)(struct burn_source *, unsigned char *buffer, int size);
/** Read subchannel data from the source (NULL if lib generated)
WARNING: This is an obscure feature with CD raw write modes.
Unless you checked the libburn code for correctness in that aspect
you should not rely on raw writing with own subchannels.
ADVICE: Set this pointer to NULL.
*/
int (*read_sub)(struct burn_source *, unsigned char *buffer, int size);
/** Get the size of the source's data. Return 0 means unpredictable
size. If application provided (*get_size) allows return 0, then
the application MUST provide a fully functional (*set_size).
*/
off_t (*get_size)(struct burn_source *);
/** Set the size of the source's data */
/* ts A70125 : BROKE BINARY BACKWARD COMPATIBILITY AT libburn-0.3.1. */
/** Program the reply of (*get_size) to a fixed value. It is advised
to implement this by a attribute off_t fixed_size; in *data .
The read() function does not have to take into respect this fake
setting. It is rather a note of libburn to itself. Eventually
necessary truncation or padding is done in libburn. Truncation
is usually considered a misburn. Padding is considered ok.
libburn is supposed to work even if (*get_size) ignores the
setting by (*set_size). But your application will not be able to
enforce fixed track sizes by burn_track_set_size() and possibly
even padding might be left out.
*/
int (*set_size)(struct burn_source *source, off_t size);
/** Clean up the source specific data */
/** Clean up the source specific data. This function will be called
once by burn_source_free() when the last referer disposes the
source.
*/
void (*free_data)(struct burn_source *);
/** Next source, for when a source runs dry and padding is disabled
THIS IS AUTOMATICALLY HANDLED, DO NOT TOUCH
WARNING: This is an obscure feature. Set to NULL at creation and
from then on leave untouched and uninterpreted.
*/
struct burn_source *next;
/** Source specific data */
/** Source specific data. Here the various source classes express their
specific properties and the instance objects store their individual
management data.
E.g. data could point to a struct like this:
struct app_burn_source
{
struct my_app *app_handle;
... other individual source parameters ...
off_t fixed_size;
};
Function (*free_data) has to be prepared to clean up and free
the struct.
*/
void *data;
/* ts A71222 : Supposed to be binary backwards compatible extension. */
/** Valid only if above member .(*read)() is NULL. This indicates a
version of struct burn_source younger than 0.
From then on, member .version tells which further members exist
in the memory layout of struct burn_source. libburn will only touch
those announced extensions.
Versions:
0 has .(*read)() != NULL, not even .version is present.
1 has .version, .(*read_xt)(), .(*cancel)()
*/
int version;
/** This substitutes for (*read)() in versions above 0. */
int (*read_xt)(struct burn_source *, unsigned char *buffer, int size);
/** Informs the burn_source that the consumer of data prematurely
ended reading. This call may or may not be issued by libburn
before (*free_data)() is called.
*/
int (*cancel)(struct burn_source *source);
};
@ -355,12 +482,12 @@ struct burn_drive_info
char product[17];
/** Revision of the drive */
char revision[5];
/** Location of the drive in the filesystem. */
/** Invalid: Was: "Location of the drive in the filesystem." */
/** This string has no meaning any more. Once it stored the persistent
drive address. Now always use function burn_drive_d_get_adr() to
inquire a persistent address. ^^^^^^ ALWAYS ^^^^^^^^ */
char location[17];
/** This is currently the string which is used as persistent
drive address. But be warned: there is NO GUARANTEE that this
will stay so. Always use function burn_drive_get_adr() to
inquire a persistent address. ^^^^^^ ALWAYS ^^^^^^ */
/** Can the drive read DVD-RAM discs */
unsigned int read_dvdram:1;
@ -515,7 +642,7 @@ struct burn_speed_descriptor {
This must be called before using any other functions in the library. It
may be called more than once with no effect.
It is possible to 'restart' the library by shutting it down and
re-initializing it. This is necessary if you follow the older and
re-initializing it. Once this was necessary if you follow the older and
more general way of accessing a drive via burn_drive_scan() and
burn_drive_grab(). See burn_drive_scan_and_grab() with its strong
urges and its explanations.
@ -602,7 +729,8 @@ void burn_preset_device_open(int exclusive, int blocking, int abort_on_busy);
/* ts A70223 */
/** Allows the use of media types which are implemented in libburn but not yet
tested. The list of those untested profiles is subject to change.
Currently it contains: 0x15 "DVD-R/DL Sequential".
Currently it contains: 0x15 "DVD-R/DL sequential recording",
0x43 "BD-RE"
If you really test such media, then please report the outcome on
libburn-hackers@pykix.org
If ever then this call should be done soon after burn_initialize() before
@ -613,31 +741,81 @@ void burn_allow_untested_profiles(int yes);
/* ts A60823 */
/** Aquire a drive with known persistent address.This is the sysadmin friendly
way to open one drive and to leave all others untouched. It bundles
the following API calls to form a non-obtrusive way to use libburn:
/** Aquire a drive with known persistent address.
This is the sysadmin friendly way to open one drive and to leave all
others untouched. It bundles the following API calls to form a
non-obtrusive way to use libburn:
burn_drive_add_whitelist() , burn_drive_scan() , burn_drive_grab()
You are *strongly urged* to use this call whenever you know the drive
address in advance.
If not, then you have to use directly above calls. In that case, you are
*strongly urged* to drop any unintended drive which will be exclusively
occupied and not closed by burn_drive_scan().
This can be done by shutting down the library including a call to
burn_finish(). You may later start a new libburn session and should then
use the function described here with an address obtained after
burn_drive_scan() via burn_drive_get_adr(&(drive_infos[driveno]), adr) .
burn_drive_scan() via burn_drive_d_get_adr(drive_infos[driveno].drive,adr).
Another way is to drop the unwanted drives by burn_drive_info_forget().
Operating on multiple drives:
Different than with burn_drive_scan() it is allowed to call
burn_drive_scan_and_grab() without giving up any other scanned drives. So
this call can be used to get a collection of more than one aquired drives.
The attempt to aquire the same drive twice will fail, though.
Pseudo-drives:
burn_drive_scan_and_grab() is able to aquire virtual drives which will
accept options much like a MMC burner drive. Many of those options will not
cause any effect, though. The address of a pseudo-drive begins with
prefix "stdio:" followed by a path.
Examples: "stdio:/tmp/pseudo_drive" , "stdio:/dev/null" , "stdio:-"
If the path is empty, the result is a null-drive = drive role 0.
It pretends to have loaded no media and supports no reading or writing.
If the path leads to an existing regular file, or to a not yet existing
file, or to an existing block device, then the result is a random access
stdio-drive capable of reading and writing = drive role 2.
If the path leads to an existing file of any type other than directory,
then the result is a sequential write-only stdio-drive = drive role 3.
The special address form "stdio:/dev/fd/<number>" is interpreted literally
as reference to open file descriptor <number>. This address form coincides
with real files on some systems, but it is in fact hardcoded in libburn.
Special address "stdio:-" means stdout = "stdio:/dev/fd/1".
The role of such a drive is determined by the file type obtained via
fstat(<number>).
Roles 2 and 3 perform all their eventual data transfer activities on a file
via standard i/o functions open(2), lseek(2), read(2), write(2), close(2).
The media profile is reported as 0xffff. Write space information from those
media is not necessarily realistic.
The capabilities of role 2 resemble DVD-RAM but it can simulate writing.
If the path does not exist in the filesystem yet, it is attempted to create
it as a regular file as soon as write operations are started.
The capabilities of role 3 resemble a blank DVD-R.
One may distinguish pseudo-drives from MMC drives by call
burn_drive_get_drive_role().
@param drive_infos On success returns a one element array with the drive
(cdrom/burner). Thus use with driveno 0 only. On failure
the array has no valid elements at all.
The returned array should be freed via burn_drive_info_free()
when it is no longer needed, and before calling a scan
function again.
when it is no longer needed.
This is a result from call burn_drive_scan(). See there.
Use with driveno 0 only.
@param adr The persistent address of the desired drive. Either obtained
by burn_drive_get_adr() or guessed skillfully by application
resp. its user.
@param adr The persistent address of the desired drive. Either once
obtained by burn_drive_d_get_adr() or composed skillfully by
application resp. its user. E.g. "/dev/sr0".
Consider to preprocess it by burn_drive_convert_fs_adr().
@param load Nonzero to make the drive attempt to load a disc (close its
tray door, etc).
@return 1 = success , 0 = drive not found , -1 = other error
@ -660,9 +838,14 @@ void burn_drive_clear_whitelist(void);
/** Scan for drives. This function MUST be called until it returns nonzero.
No drives may be in use when this is called.
All drive pointers are invalidated by using this function. Do NOT store
drive pointers across calls to this function or death AND pain will ensue.
In case of re-scanning:
All pointers to struct burn_drive and all struct burn_drive_info arrays
are invalidated by using this function. Do NOT store drive pointers across
calls to this function !
To avoid invalid pointers one MUST free all burn_drive_info arrays
by burn_drive_info_free() before calling burn_drive_scan() a second time.
If there are drives left, then burn_drive_scan() will refuse to work.
After this call all drives depicted by the returned array are subject
to eventual (O_EXCL) locking. See burn_preset_device_open(). This state
ends either with burn_drive_info_forget() or with burn_drive_release().
@ -709,15 +892,25 @@ void burn_drive_info_free(struct burn_drive_info drive_infos[]);
#define BURN_DRIVE_ADR_LEN 1024
/** Inquire the persistent address of the given drive.
@param drive_info The drive to inquire. Usually some &(drive_infos[driveno])
@param drive The drive to inquire.
@param adr An application provided array of at least BURN_DRIVE_ADR_LEN
characters size. The persistent address gets copied to it.
@return >0 success , <=0 error (due to libburn internal problem)
*/
int burn_drive_d_get_adr(struct burn_drive *drive, char adr[]);
/** Inquire the persistent address of a drive via a given drive_info object.
(Note: This is a legacy call.)
@param drive_info The drive to inquire.Usually some &(drive_infos[driveno])
@param adr An application provided array of at least BURN_DRIVE_ADR_LEN
characters size. The persistent address gets copied to it.
@return >0 success , <=0 error (due to libburn internal problem)
*/
int burn_drive_get_adr(struct burn_drive_info *drive_info, char adr[]);
/* ts A60922 ticket 33 */
/** Evaluate wether the given address would be a possible persistent drive
/** Evaluate whether the given address would be a possible persistent drive
address of libburn.
@return 1 means yes, 0 means no
*/
@ -756,7 +949,7 @@ int burn_drive_convert_scsi_adr(int bus_no, int host_no, int channel_no,
/* ts A60923 - A61005 */
/** Try to obtain bus,host,channel,target,lun from path. If there is an SCSI
address at all, then this call should succeed with a persistent
drive address obtained via burn_drive_get_adr(). It is also supposed to
drive address obtained via burn_drive_d_get_adr(). It is also supposed to
succeed with any device file of a (possibly emulated) SCSI device.
@return 1 = success , 0 = failure , -1 = severe error
*/
@ -776,13 +969,25 @@ int burn_drive_grab(struct burn_drive *drive, int load);
/** Release a drive. This should not be done until the drive is no longer
busy (see burn_drive_get_status).
Linux: The drive is unlocked afterwards. (O_EXCL , F_SETLK).
Linux: The drive device file is not reserved afterwards. (O_EXCL, F_SETLK).
@param drive The drive to release.
@param eject Nonzero to make the drive eject the disc in it.
*/
void burn_drive_release(struct burn_drive *drive, int eject);
/* ts A70918 */
/** Like burn_drive_release() but keeping the drive tray closed and its
eject button disabled. This physically locked drive state will last until
the drive is grabbed again and released via burn_drive_release().
Programs like eject, cdrecord, growisofs will break that ban too.
@param drive The drive to release and leave locked.
@param flag Bitfield for control purposes (unused yet, submit 0)
@return 1 means success, <=0 means failure
*/
int burn_drive_leave_locked(struct burn_drive *d, int flag);
/** Returns what kind of disc a drive is holding. This function may need to be
called more than once to get a proper status from it. See burn_disc_status
for details.
@ -884,19 +1089,25 @@ off_t burn_disc_available_space(struct burn_drive *d,
/* ts A61202 */
/** Tells the MMC Profile identifier of the loaded media. The drive must be
grabbed in order to get a non-zero result.
libburn currently writes only to profiles 0x09 "CD-R", 0x0a "CD-RW",
0x11 "DVD-R", 0x12 "DVD-RAM", 0x13 "DVD-RW restricted overwrite",
0x14 "DVD-RW Sequential Recording" or 0x1a "DVD+RW".
If enabled by burn_allow_untested_profiles() it also writes to profile
0x15 "DVD-R/DL Sequential Recording".
libburn currently writes only to profiles
0x09 "CD-R", 0x0a "CD-RW",
0x11 "DVD-R sequential recording", 0x12 "DVD-RAM",
0x13 "DVD-RW restricted overwrite", 0x14 "DVD-RW sequential recording",
0x1a "DVD+RW", 0x1b "DVD+R"
0x2b "DVD+R/DL"
If enabled by burn_allow_untested_profiles() it also writes to profiles
0x15 "DVD-R/DL sequential recording", 0x43 "BD-RE".
Writeable stdio-drives return this profile:
0xffff "stdio file"
@param d The drive where the media is inserted.
@param pno Profile Number as of mmc5r03c.pdf, table 89
@param name Profile Name (e.g "CD-RW", unknown profiles have empty name)
@param name Profile Name (see above list, unknown profiles have empty name)
@return 1 profile is valid, 0 no profile info available
*/
int burn_disc_get_profile(struct burn_drive *d, int *pno, char name[80]);
/** Tells whether a disc can be erased or not
@param d The drive to inquire.
@return Non-zero means erasable
*/
int burn_disc_erasable(struct burn_drive *d);
@ -916,6 +1127,15 @@ enum burn_drive_status burn_drive_get_status(struct burn_drive *drive,
*/
struct burn_write_opts *burn_write_opts_new(struct burn_drive *drive);
/* ts A70901 */
/** Inquires the drive associated with a burn_write_opts object.
@param opts object to inquire
@return pointer to drive
*/
struct burn_drive *burn_write_opts_get_drive(struct burn_write_opts *opts);
/** Frees a write_opts struct created with burn_write_opts_new
@param opts write_opts to free
*/
@ -1036,7 +1256,7 @@ void burn_disc_read(struct burn_drive *drive, const struct burn_read_opts *o);
/* ts A70219 */
/** Examines a completed setup for burn_disc_write() wether it is permissible
/** Examines a completed setup for burn_disc_write() whether it is permissible
with drive and media. This function is called by burn_disc_write() but
an application might be interested in this check in advance.
@param o The options for the writing operation.
@ -1048,9 +1268,6 @@ void burn_disc_read(struct burn_drive *drive, const struct burn_read_opts *o);
int burn_precheck_write(struct burn_write_opts *o, struct burn_disc *disc,
char reasons[BURN_REASONS_LEN], int silent);
/* <<< enabling switch for internal usage and trust in this function */
#define Libburn_precheck_write_ruleS 1
/** Write a disc in the drive. The drive must be grabbed successfully before
calling this function. Always ensure that the drive reports a status of
@ -1058,6 +1275,9 @@ int burn_precheck_write(struct burn_write_opts *o, struct burn_disc *disc,
Note: write_type BURN_WRITE_SAO is currently not capable of writing a mix
of data and audio tracks. You must use BURN_WRITE_TAO for such sessions.
To be set by burn_write_opts_set_write_type().
Note: This function is not suitable for overwriting data in the middle of
a valid data area because it is allowed to append trailing data.
For exact random access overwriting use burn_random_access_write().
@param o The options for the writing operation.
@param disc The struct burn_disc * that described the disc to be created
*/
@ -1072,7 +1292,7 @@ void burn_drive_cancel(struct burn_drive *drive);
/* ts A61223 */
/** Inquire wether the most recent write run was successful. Reasons for
/** Inquire whether the most recent write run was successful. Reasons for
non-success may be: rejection of burn parameters, abort during fatal errors
during write, a call to burn_drive_cancel() by the application thread.
@param d The drive to inquire.
@ -1113,7 +1333,9 @@ int burn_msf_to_lba(int m, int s, int f);
*/
void burn_lba_to_msf(int lba, int *m, int *s, int *f);
/** Create a new disc */
/** Create a new disc
@return Pointer to a burn_disc object or NULL on failure.
*/
struct burn_disc *burn_disc_create(void);
/** Delete disc and decrease the reference count on all its sessions
@ -1121,7 +1343,9 @@ struct burn_disc *burn_disc_create(void);
*/
void burn_disc_free(struct burn_disc *d);
/** Create a new session */
/** Create a new session
@return Pointer to a burn_session object or NULL on failure.
*/
struct burn_session *burn_session_create(void);
/** Free a session (and decrease reference count on all tracks inside)
@ -1185,7 +1409,7 @@ void burn_track_define_data(struct burn_track *t, int offset, int tail,
/* ts A61024 */
/** Define wether a track shall swap bytes of its input stream.
/** Define whether a track shall swap bytes of its input stream.
@param t The track to change
@param swap_source_bytes 0=do not swap, 1=swap byte pairs
@return 1=success , 0=unacceptable value
@ -1250,7 +1474,12 @@ int burn_track_set_default_size(struct burn_track *t, off_t size);
*/
void burn_source_free(struct burn_source *s);
/** Creates a data source for an image file (and maybe subcode file) */
/** Creates a data source for an image file (and maybe subcode file)
@param path The file address for the main channel payload.
@param subpath Eventual address for subchannel data. Only used in exotic
raw write modes. Submit NULL for normal tasks.
@return Pointer to a burn_source object, NULL indicates failure
*/
struct burn_source *burn_file_source_new(const char *path,
const char *subpath);
@ -1258,17 +1487,74 @@ struct burn_source *burn_file_source_new(const char *path,
readable filedescriptor, an eventually open readable subcodes file
descriptor and eventually a fixed size in bytes.
@param datafd The source of data.
@param subfd The eventual source for subcodes. Not used if -1.
@param subfd The eventual source of subchannel data. Only used in exotic
raw write modes. Submit -1 for normal tasks.
@param size The eventual fixed size of eventually both fds.
If this value is 0, the size will be determined from datafd.
@return Pointer to a burn_source object, NULL indicates failure
*/
struct burn_source *burn_fd_source_new(int datafd, int subfd, off_t size);
/* ts A70930 */
/** Creates a fifo which acts as proxy for an already existing data source.
The fifo provides a ring buffer which shall smoothen the data stream
between burn_source and writer thread. Each fifo serves only for one
data source and gets attached to one track as its only data source
by burn_track_set_source().
A fifo starts its life in "standby" mode with no buffer space allocated.
As soon as its track requires bytes, the fifo establishes a worker thread
and allocates its buffer. After input has ended and all buffer content is
consumed, the buffer space gets freed and the worker thread ends.
This happens asynchronously. So expect two buffers and worker threads to
exist for a short time between tracks. Be modest in your size demands if
multiple tracks are to be expected.
@param inp The burn_source for which the fifo shall act as proxy.
It can be disposed by burn_source_free() immediately
after this call.
@param chunksize The size in bytes of a chunk. Use 2048 for sources
suitable for BURN_BLOCK_MODE1 and 2352 for sources
which deliver for BURN_BLOCK_AUDIO.
Some variations of burn_source might work only with
a particular chunksize. E.g. libisofs demands 2048.
@param chunks The number of chunks to be allocated in ring buffer.
This value must be >= 2.
@param flag Bitfield for control purposes (unused yet, submit 0).
@return A pointer to the newly created burn_source.
Later both burn_sources, inp and the returned fifo, have
to be disposed by calling burn_source_free() for each.
inp can be freed immediately, the returned fifo may be
kept as handle for burn_fifo_inquire_status().
*/
struct burn_source *burn_fifo_source_new(struct burn_source *inp,
int chunksize, int chunks, int flag);
/* ts A71003 */
/** Inquires state and fill parameters of a fifo burn_source which was created
by burn_fifo_source_new() . Do not use with other burn_source variants.
@param fifo The fifo object to inquire
@param size The total size of the fifo
@param free_bytes The current free capacity of the fifo
@param status_text Returns a pointer to a constant text, see below
@return <0 reply invalid, >=0 fifo status code:
bit0+1=input status, bit2=consumption status, i.e:
0="standby" : data processing not started yet
1="active" : input and consumption are active
2="ending" : input has ended without error
3="failing" : input had error and ended,
4="unused" : ( consumption has ended before processing start )
5="abandoned" : consumption has ended prematurely
6="ended" : consumption has ended without input error
7="aborted" : consumption has ended after input error
*/
int burn_fifo_inquire_status(struct burn_source *fifo, int *size,
int *free_bytes, char **status_text);
/* ts A70328 */
/** Sets a fixed track size after the data source object has already been
created.
@param t The track to poperate on
@param t The track to operate on
@param size the number of bytes to use as track size
@return <=0 indicates failure , >0 success
*/
@ -1303,7 +1589,7 @@ void burn_drive_set_speed(struct burn_drive *d, int read, int write);
be full. To check and wait for enough free buffer space before writing
will move the task of waiting from the operating system's device driver
to libburn. While writing is going on and waiting is enabled, any write
operation will be checked wether it will fill the drive buffer up to
operation will be checked whether it will fill the drive buffer up to
more than max_percent. If so, then waiting will happen until the buffer
fill is predicted with at most min_percent.
Thus: if min_percent < max_percent then transfer rate will oscillate.
@ -1386,9 +1672,19 @@ void burn_write_opts_set_toc_entries(struct burn_write_opts *opts,
*/
void burn_write_opts_set_format(struct burn_write_opts *opts, int format);
/** Sets the simulate value for the write_opts struct
/** Sets the simulate value for the write_opts struct .
This corresponds to the Test Write bit in MMC mode page 05h. Several media
types do not support this. See struct burn_multi_caps.might_simulate for
actual availability of this feature.
If the media is suitable, the drive will perform burn_write_disc() as a
simulation instead of effective write operations. This means that the
media content and burn_disc_get_status() stay unchanged.
Note: With stdio-drives, the target file gets eventually created, opened,
lseeked, and closed, but not written. So there are effects on it.
Warning: Call burn_random_access_write() will never do simulation because
it does not get any burn_write_opts.
@param opts The write opts to change
@param sim If non-zero, the drive will perform a simulation instead of a burn
@param sim Non-zero enables simulation, 0 enables real writing
@return Returns 1 on success and 0 on failure.
*/
int burn_write_opts_set_simulate(struct burn_write_opts *opts, int sim);
@ -1417,6 +1713,7 @@ void burn_write_opts_set_mediacatalog(struct burn_write_opts *opts, unsigned cha
/* ts A61106 */
/** Sets the multi flag which eventually marks the emerging session as not
being the last one and thus creating a BURN_DISC_APPENDABLE media.
@param opts The option object to be manipulated
@param multi 1=media will be appendable, 0=media will be closed (default)
*/
void burn_write_opts_set_multi(struct burn_write_opts *opts, int multi);
@ -1424,11 +1721,14 @@ void burn_write_opts_set_multi(struct burn_write_opts *opts, int multi);
/* ts A61222 */
/** Sets a start address for writing to media and write modes which allow to
choose this address at all (DVD+RW, DVD-RAM, formatted DVD-RW only for
choose this address at all (for now: DVD+RW, DVD-RAM, formatted DVD-RW).
now). The address is given in bytes. If it is not -1 then a write run
will fail if choice of start address is not supported or if the block
alignment of the address is not suitable for media and write mode.
(Alignment to 32 kB blocks is advised with DVD media.)
Alignment to 32 kB blocks is supposed to be safe with DVD media.
Call burn_disc_get_multi_caps() can obtain the necessary media info. See
resulting struct burn_multi_caps elements .start_adr , .start_alignment ,
.start_range_low , .start_range_high .
@param opts The write opts to change
@param value The address in bytes (-1 = start at default address)
*/
@ -1439,7 +1739,7 @@ void burn_write_opts_set_start_byte(struct burn_write_opts *opts, off_t value);
/** Caution: still immature and likely to change. Problems arose with
sequential DVD-RW on one drive.
Controls wether the whole available space of the media shall be filled up
Controls whether the whole available space of the media shall be filled up
by the last track of the last session.
@param opts The write opts to change
@param fill_up_media If 1 : fill up by last track, if 0 = do not fill up
@ -1450,8 +1750,8 @@ void burn_write_opts_set_fillup(struct burn_write_opts *opts,
/* ts A70303 */
/** Eventually makes libburn ignore the failure of some conformance checks:
- the check wether CD write+block type is supported by the drive
- the check wether the media profile supports simulated burning
- the check whether CD write+block type is supported by the drive
- the check whether the media profile supports simulated burning
@param opts The write opts to change
@param use_force 1=ignore above checks, 0=refuse work on failed check
*/
@ -1558,7 +1858,7 @@ int burn_drive_get_speedlist(struct burn_drive *d,
/** Look up the fastest speed descriptor which is not faster than the given
speed_goal. If it is 0, then the fastest one is chosen among the
descriptors with the highest end_lba. If it is -1 then the slowest speed
descriptor is chosen regardless of end_lba. Parameter flag decides wether
descriptor is chosen regardless of end_lba. Parameter flag decides whether
the speed goal means write speed or read speed.
@param d Drive to query
@param speed_goal Upper limit for speed,
@ -1737,7 +2037,9 @@ int burn_track_get_mode(struct burn_track *track);
*/
int burn_session_get_hidefirst(struct burn_session *session);
/** Returns the library's version in its parts
/** Returns the library's version in its parts.
This is the runtime counterpart of the three build time macros
burn_header_version_* below.
@param major The major version number
@param minor The minor version number
@param micro The micro version number
@ -1745,10 +2047,80 @@ int burn_session_get_hidefirst(struct burn_session *session);
void burn_version(int *major, int *minor, int *micro);
/* ts A80129 */
/** These three release version numbers tell the revision of this header file
and of the API it describes. They are memorized by applications at build
time.
Immediately after burn_initialize() an application should do this check:
burn_version(&major, &minor, &micro);
if(major > burn_header_version_major
|| (major == burn_header_version_major
&& (minor > burn_header_version_minor
|| (minor == burn_header_version_minor
&& micro >= burn_header_version_micro)))) {
... Young enough. Go on with program run ....
} else {
... Too old. Do not use this libburn version ...
}
*/
#define burn_header_version_major 0
#define burn_header_version_minor 4
#define burn_header_version_micro 4
/** Note:
Above version numbers are also recorded in configure.ac because libtool
wants them as parameters at build time.
For the library compatibility check BURN_*_VERSION in configure.ac
are not decisive. Only the three numbers above do matter.
*/
/** Usage discussion:
Some developers of the libburnia project have differing
opinions how to ensure the compatibility of libaries
and applications.
It is about whether to use at compile time and at runtime
the version numbers isoburn_header_version_* provided here.
Thomas Schmitt advises to use them.
Vreixo Formoso advises to use other means.
At compile time:
Vreixo Formoso advises to leave proper version matching
to properly programmed checks in the the application's
build system, which will eventually refuse compilation.
Thomas Schmitt advises to use the macros defined here
for comparison with the application's requirements of
library revisions and to eventually break compilation.
Both advises are combinable. I.e. be master of your
build system and have #if checks in the source code
of your application, nevertheless.
At runtime (via *_is_compatible()):
Vreixo Formoso advises to compare the application's
requirements of library revisions with the runtime
library. This is to allow runtime libraries which are
young enough for the application but too old for
the lib*.h files seen at compile time.
Thomas Schmitt advises to compare the header
revisions defined here with the runtime library.
This is to enforce a strictly monotonous chain
of revisions from app to header to library,
at the cost of excluding some older libraries.
These two advises are mutually exclusive.
*/
/* ts A60924 : ticket 74 */
/** Control queueing and stderr printing of messages from libburn.
Severity may be one of "NEVER", "FATAL", "SORRY", "WARNING", "HINT",
"NOTE", "UPDATE", "DEBUG", "ALL".
Severity may be one of "NEVER", "ABORT", "FATAL", "FAILURE", "SORRY",
"WARNING", "HINT", "NOTE", "UPDATE", "DEBUG", "ALL".
@param queue_severity Gives the minimum limit for messages to be queued.
Default: "NEVER". If you queue messages then you
must consume them by burn_msgs_obtain().
@ -1767,8 +2139,9 @@ int burn_msgs_set_severities(char *queue_severity,
/** Obtain the oldest pending libburn message from the queue which has at
least the given minimum_severity. This message and any older message of
lower severity will get discarded from the queue and is then lost forever.
@param minimum_severity may be one of "NEVER", "FATAL", "SORRY",
"WARNING", "HINT", "NOTE", "UPDATE", "DEBUG", "ALL".
@param minimum_severity may be one of "NEVER", "ABORT", "FATAL",
"FAILURE", "SORRY", "WARNING", "HINT", "NOTE", "UPDATE",
"DEBUG", "ALL".
To call with minimum_severity "NEVER" will discard the
whole queue.
@param error_code Will become a unique error code as liste in
@ -1784,8 +2157,60 @@ int burn_msgs_obtain(char *minimum_severity,
char severity[]);
/* ts A70922 */
/** Submit a message to the libburn queueing system. It will be queued or
printed as if it was generated by libburn itself.
@param error_code The unique error code of your message.
Submit 0 if you do not have reserved error codes within
the libburnia project.
@param msg_text Not more than BURN_MSGS_MESSAGE_LEN characters of
message text.
@param os_errno Eventual errno related to the message. Submit 0 if
the message is not related to a operating system error.
@param severity One of "ABORT", "FATAL", "FAILURE", "SORRY", "WARNING",
"HINT", "NOTE", "UPDATE", "DEBUG". Defaults to "FATAL".
@param d An eventual drive to which the message shall be related.
Submit NULL if the message is not specific to a
particular drive object.
@return 1 if message was delivered, <=0 if failure
*/
int burn_msgs_submit(int error_code, char msg_text[], int os_errno,
char severity[], struct burn_drive *d);
/* ts A71016 */
/** Convert a severity name into a severity number, which gives the severity
rank of the name.
@param severity_name A name as with burn_msgs_submit(), e.g. "SORRY".
@param severity_number The rank number: the higher, the more severe.
@param flag Bitfield for control purposes (unused yet, submit 0)
@return >0 success, <=0 failure
*/
int burn_text_to_sev(char *severity_name, int *severity_number, int flag);
/* ts A80202 : @since 0.4.4 */
/** Convert a severity number into a severity name
@param severity_number The rank number: the higher, the more severe.
@param severity_name A name as with burn_msgs_submit(), e.g. "SORRY".
@param flag Bitfield for control purposes (unused yet, submit 0)
*/
int burn_sev_to_text(int severity_number, char **severity_name, int flag);
/* ts A70915 */
/** Replace the messenger object handle of libburn by a compatible handle
obtained from a related library.
See also: libisofs, API function iso_get_messenger().
@param messenger The foreign but compatible message handle.
@return 1 : success, <=0 : failure
*/
int burn_set_messenger(void *messenger);
/* ts A61002 */
/* The prototype of a handler function suitable for burn_set_abort_handling().
/** The prototype of a handler function suitable for burn_set_abort_handling().
Such a function has to return -2 if it does not want the process to
exit with value 1.
*/
@ -1807,6 +2232,102 @@ typedef int (*burn_abort_handler_t)(void *handle, int signum, int flag);
void burn_set_signal_handling(void *handle, burn_abort_handler_t handler,
int mode);
/* ts A70811 */
/** Write data in random access mode.
The drive must be grabbed successfully before calling this function which
circumvents usual libburn session processing and rather writes data without
preparations or finalizing. This will work only with overwriteable media
which are also suitable for burn_write_opts_set_start_byte(). The same
address alignment restrictions as with this function apply. I.e. for DVD
it is best to align to 32 KiB blocks (= 16 LBA units). The amount of data
to be written is subject to the same media dependent alignment rules.
Again, 32 KiB is most safe.
Call burn_disc_get_multi_caps() can obtain the necessary media info. See
resulting struct burn_multi_caps elements .start_adr , .start_alignment ,
.start_range_low , .start_range_high .
Other than burn_disc_write() this is a synchronous call which returns
only after the write transaction has ended (sucessfully or not). So it is
wise not to transfer giant amounts of data in a single call.
Important: Data have to fit into the already formatted area of the media.
@param d The drive to which to write
@param byte_address The start address of the write in byte
(1 LBA unit = 2048 bytes) (do respect media alignment)
@param data The bytes to be written
@param data_count The number of those bytes (do respect media alignment)
data_count == 0 is permitted (e.g. to flush the
drive buffer without further data transfer).
@param flag Bitfield for control purposes:
bit0 = flush the drive buffer after eventual writing
@return 1=sucessful , <=0 : number of transfered bytes * -1
*/
int burn_random_access_write(struct burn_drive *d, off_t byte_address,
char *data, off_t data_count, int flag);
/* ts A70812 */
/** Read data in random access mode.
The drive must be grabbed successfully before calling this function.
With all currently supported drives and media the byte_address has to
be aligned to 2048 bytes. Only data tracks with 2048 bytes per sector
can be read this way. I.e. not CD-audio, not CD-video-stream ...
This is a synchronous call which returns only after the full read job
has ended (sucessfully or not). So it is wise not to read giant amounts
of data in a single call.
@param d The drive to which to write
@param byte_address The start address of the read in byte (aligned to 2048)
@param data A memory buffer capable of taking data_size bytes
@param data_size The amount of data to be read. This does not have to
be aligned to any block size.
@param data_count The amount of data actually read (interesting on error)
@param flag Bitfield for control purposes:
bit0= - reserved -
bit1= do not submit error message if read error
@return 1=sucessful , <=0 an error occured
*/
int burn_read_data(struct burn_drive *d, off_t byte_address,
char data[], off_t data_size, off_t *data_count, int flag);
/* A70904 */
/** Inquire whether the drive object is a real MMC drive or a pseudo-drive
created by a stdio: address.
@param d The drive to inquire
@return 0= null-drive
1= real MMC drive
2= stdio-drive, random access, read-write
3= stdio-drive, sequential, write-only
*/
int burn_drive_get_drive_role(struct burn_drive *d);
/* ts A70923 */
/** Find out whether a given address string would lead to the given drive
object. This should be done in advance for track source addresses
with parameter drive_role set to 2.
Although a real MMC drive should hardly exist as two drive objects at
the same time, this can easily happen with stdio-drives. So if more than
one drive is used by the application, then this gesture is advised:
burn_drive_d_get_adr(d2, adr2);
if (burn_drive_equals_adr(d1, adr2, burn_drive_get_drive_role(d2)))
... Both drive objects point to the same storage facility ...
@param d1 Existing drive object
@param adr2 Address string to be tested. Prefix "stdio:" overrides
parameter drive_role2 by either 0 or 2 as appropriate.
The string must be shorter than BURN_DRIVE_ADR_LEN.
@param drive_role2 Role as burn_drive_get_drive_role() would attribute
to adr2 if it was a drive. Use value 2 for checking track
sources resp. pseudo-drive addresses without "stdio:".
Use 1 for checking drive addresses including those with
prefix "stdio:".
@return 1= adr2 leads to d1 , 0= adr2 seems not to lead to d1,
-1 = adr2 is bad
*/
int burn_drive_equals_adr(struct burn_drive *d1, char *adr2, int drive_role2);
#ifndef DOXYGEN
BURN_END_DECLS

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 - 2008 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,8 +1,8 @@
/* libdax_msgs
Message handling facility of libdax.
Copyright (C) 2006-2007 Thomas Schmitt <scdbackup@gmx.net>,
provided under GPL
Copyright (C) 2006-2008 Thomas Schmitt <scdbackup@gmx.net>,
provided under GPL version 2
*/
@ -23,7 +23,7 @@ struct libdax_msgs_item {
double timestamp;
pid_t process_id;
int driveno;
int origin;
int severity;
int priority;
@ -43,6 +43,8 @@ struct libdax_msgs_item {
struct libdax_msgs {
int refcount;
struct libdax_msgs_item *oldest;
struct libdax_msgs_item *youngest;
int count;
@ -68,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 */
@ -86,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
@ -113,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
@ -134,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
@ -146,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
*/
@ -160,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.
@ -180,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
@ -256,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);
@ -276,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
@ -284,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
------------------------------------------------------------------------------
@ -304,6 +431,7 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
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
General library operations:
@ -313,7 +441,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
@ -371,7 +499,31 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
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
libdax_audioxtr:
0x00020200 (SORRY,HIGH) = Cannot open audio source file
@ -379,6 +531,117 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
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
------------------------------------------------------------------------------
#endif /* LIDBAX_MSGS_________________ */

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

View File

@ -91,6 +91,8 @@ extern struct libdax_msgs *libdax_messenger;
ts A70208 : Finally made tests with DVD-R. Worked exactly as new DVD-RW.
ts A70306 : Implemented DVD+R (always -multi for now)
ts A70330 : Allowed finalizing of DVD+R.
ts A80228 : Made DVD+R/DL support official after nightmorph reported success
in http://libburnia-project.org/ticket/13
*/
/* ts A70519 : With MMC commands of data direction FROM_DRIVE:
@ -116,6 +118,7 @@ extern struct libdax_msgs *libdax_messenger;
static unsigned char MMC_GET_MSINFO[] =
{ 0x43, 0, 1, 0, 0, 0, 0, 16, 0, 0 };
static unsigned char MMC_GET_TOC[] = { 0x43, 2, 2, 0, 0, 0, 0, 16, 0, 0 };
static unsigned char MMC_GET_TOC_FMT0[] = { 0x43, 0, 0, 0, 0, 0, 0, 16, 0, 0 };
static unsigned char MMC_GET_ATIP[] = { 0x43, 2, 4, 0, 0, 0, 0, 16, 0, 0 };
static unsigned char MMC_GET_DISC_INFO[] =
{ 0x51, 0, 0, 0, 0, 0, 0, 16, 0, 0 };
@ -165,15 +168,32 @@ static unsigned char MMC_READ_FORMAT_CAPACITIES[] =
static unsigned char MMC_RESERVE_TRACK[] =
{ 0x53, 0, 0, 0, 0, 0, 0, 0, 0, 0};
/* ts A70812 : Read data sectors (for types with 2048 bytes/sector only) */
static unsigned char MMC_READ_10[] =
{ 0x28, 0, 0, 0, 0, 0, 0, 0, 0, 0};
static int mmc_function_spy_do_tell = 0;
int mmc_function_spy(char * text)
int mmc_function_spy(struct burn_drive *d, char * text)
{
if (mmc_function_spy_do_tell)
fprintf(stderr,"libburn: experimental: mmc_function_spy: %s\n",
text);
if (d == NULL)
return 1;
if (d->drive_role != 1) {
char msg[4096];
sprintf(msg, "Emulated drive caught in SCSI adapter \"%s\"",
text);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002014c,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
d->cancel = 1;
return 0;
}
return 1;
}
@ -208,7 +228,8 @@ void mmc_send_cue_sheet(struct burn_drive *d, struct cue_sheet *s)
struct command c;
mmc_function_spy("mmc_send_cue_sheet");
if (mmc_function_spy(d, "mmc_send_cue_sheet") <= 0)
return;
scsi_init_command(&c, MMC_SEND_CUE_SHEET, sizeof(MMC_SEND_CUE_SHEET));
/*
@ -238,7 +259,9 @@ int mmc_reserve_track(struct burn_drive *d, off_t size)
int lba;
char msg[80];
mmc_function_spy("mmc_reserve_track");
if (mmc_function_spy(d, "mmc_reserve_track") <= 0)
return 0;
scsi_init_command(&c, MMC_RESERVE_TRACK, sizeof(MMC_RESERVE_TRACK));
/*
c.oplen = sizeof(MMC_RESERVE_TRACK);
@ -270,7 +293,8 @@ int mmc_read_track_info(struct burn_drive *d, int trackno, struct buffer *buf,
{
struct command c;
mmc_function_spy("mmc_read_track_info");
if (mmc_function_spy(d, "mmc_read_track_info") <= 0)
return 0;
scsi_init_command(&c, MMC_TRACK_INFO, sizeof(MMC_TRACK_INFO));
/*
@ -284,8 +308,9 @@ int mmc_read_track_info(struct burn_drive *d, int trackno, struct buffer *buf,
c.opcode[1] = 1;
if(trackno<=0) {
if (d->current_profile == 0x1a || d->current_profile == 0x13 ||
d->current_profile == 0x12 )
/* DVD+RW , DVD-RW restricted overwrite , DVD-RAM */
d->current_profile == 0x12 || d->current_profile == 0x43)
/* DVD+RW , DVD-RW restricted overwrite , DVD-RAM
BD-RE */
trackno = 1;
else if (d->current_profile == 0x10 ||
d->current_profile == 0x11 ||
@ -316,7 +341,8 @@ int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa)
int ret, num, alloc_len = 20;
unsigned char *data;
mmc_function_spy("mmc_get_nwa");
if (mmc_function_spy(d, "mmc_get_nwa") <= 0)
return -1;
ret = mmc_read_track_info(d, trackno, &buf, alloc_len);
if (ret <= 0)
@ -326,7 +352,7 @@ int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa)
*nwa = mmc_four_char_to_int(data + 12);
num = mmc_four_char_to_int(data + 16);
if (d->current_profile == 0x1a || d->current_profile == 0x13 ||
d->current_profile == 0x12) {
d->current_profile == 0x12 || d->current_profile == 0x43) {
/* overwriteable */
*lba = *nwa = num = 0;
} else if (!(data[7]&1)) {
@ -354,9 +380,10 @@ int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa)
/* void mmc_close_disc(struct burn_drive *d, struct burn_write_opts *o) */
void mmc_close_disc(struct burn_write_opts *o)
{
struct burn_drive *d;
struct burn_drive *d = o->drive;
mmc_function_spy("mmc_close_disc");
if (mmc_function_spy(d, "mmc_close_disc") <= 0)
return;
libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
@ -364,7 +391,6 @@ void mmc_close_disc(struct burn_write_opts *o)
/* ts A61009 : made impossible by removing redundant parameter d */
/* a ssert(o->drive == d); */
d = o->drive;
o->multi = 0;
spc_select_write_params(d, o);
@ -375,9 +401,10 @@ void mmc_close_disc(struct burn_write_opts *o)
/* void mmc_close_session(struct burn_drive *d, struct burn_write_opts *o) */
void mmc_close_session(struct burn_write_opts *o)
{
struct burn_drive *d;
struct burn_drive *d = o->drive;
mmc_function_spy("mmc_close_session");
if (mmc_function_spy(d, "mmc_close_session") <= 0)
return;
libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
@ -385,7 +412,6 @@ void mmc_close_session(struct burn_write_opts *o)
/* ts A61009 : made impossible by removing redundant parameter d */
/* a ssert(o->drive == d); */
d = o->drive;
o->multi = 3;
spc_select_write_params(d, o);
@ -401,7 +427,8 @@ void mmc_close(struct burn_drive *d, int session, int track)
{
struct command c;
mmc_function_spy("mmc_close");
if (mmc_function_spy(d, "mmc_close") <= 0)
return;
scsi_init_command(&c, MMC_CLOSE, sizeof(MMC_CLOSE));
/*
@ -410,6 +437,8 @@ void mmc_close(struct burn_drive *d, int session, int track)
*/
c.retry = 1;
c.opcode[1] |= 1; /* ts A70918 : Immed */
/* (ts A61030 : shifted !!session rather than or-ing plain session ) */
c.opcode[2] = ((session & 3) << 1) | !!track;
c.opcode[4] = track >> 8;
@ -417,6 +446,14 @@ void mmc_close(struct burn_drive *d, int session, int track)
c.page = NULL;
c.dir = NO_TRANSFER;
d->issue_command(d, &c);
/* ts A70918 : Immed : wait for drive to complete command */
if (c.error) {
d->cancel = 1;
return;
}
if (spc_wait_unit_attention(d, 3600, "CLOSE TRACK SESSION", 0) <= 0)
d->cancel = 1;
}
void mmc_get_event(struct burn_drive *d)
@ -425,7 +462,8 @@ void mmc_get_event(struct burn_drive *d)
struct command c;
int alloc_len= 8;
mmc_function_spy("mmc_get_event");
if (mmc_function_spy(d, "mmc_get_event") <= 0)
return;
scsi_init_command(&c, MMC_GET_EVENT, sizeof(MMC_GET_EVENT));
/*
@ -495,7 +533,7 @@ static int mmc_wait_for_buffer_free(struct burn_drive *d, struct buffer *buf)
/* There is need to inquire the buffer fill */
d->pessimistic_writes++;
min_fac = ((double) d->wfb_min_percent) / 100.0;
gettimeofday(&t0,&dummy_tz);
gettimeofday(&t0, &dummy_tz);
#ifdef Libburn_mmc_wfb_debuG
sleeplist[0]= 0;
sprintf(sleeplist,"(%d%s %d)",
@ -590,7 +628,9 @@ void mmc_write_12(struct burn_drive *d, int start, struct buffer *buf)
struct command c;
int len;
mmc_function_spy("mmc_write_12");
if (mmc_function_spy(d, "mmc_write_12") <= 0)
return;
len = buf->sectors;
/* ts A61009 */
@ -630,11 +670,10 @@ int mmc_write(struct burn_drive *d, int start, struct buffer *buf)
O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR);
#endif /* Libburn_log_in_and_out_streaM */
mmc_function_spy("mmc_write");
pthread_mutex_lock(&d->access_lock);
cancelled = d->cancel;
pthread_mutex_unlock(&d->access_lock);
if (mmc_function_spy(d, "mmc_write") <= 0)
return BE_CANCELLED;
cancelled = d->cancel;
if (cancelled)
return BE_CANCELLED;
@ -709,9 +748,7 @@ int mmc_write(struct burn_drive *d, int start, struct buffer *buf)
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
}
pthread_mutex_lock(&d->access_lock);
d->cancel = 1;
pthread_mutex_unlock(&d->access_lock);
return BE_CANCELLED;
}
@ -764,6 +801,153 @@ int mmc_fake_toc_entry(struct burn_toc_entry *entry, int session_number,
}
/* ts A71128 : for DVD-ROM drives which offer no reliable track information */
static int mmc_read_toc_fmt0_al(struct burn_drive *d, int *alloc_len)
{
struct burn_track *track;
struct burn_session *session;
struct burn_toc_entry *entry;
struct buffer buf;
struct command c;
int dlen, i, old_alloc_len, session_number, prev_session = -1;
int lba, size;
unsigned char *tdata, size_data[4], start_data[4];
if (*alloc_len < 4)
return 0;
scsi_init_command(&c, MMC_GET_TOC_FMT0, sizeof(MMC_GET_TOC_FMT0));
c.dxfer_len = *alloc_len;
c.opcode[7] = (c.dxfer_len >> 8) & 0xff;
c.opcode[8] = c.dxfer_len & 0xff;
c.retry = 1;
c.page = &buf;
c.page->bytes = 0;
c.page->sectors = 0;
c.dir = FROM_DRIVE;
d->issue_command(d, &c);
if (c.error) {
err_ex:;
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002010d,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
"Could not inquire TOC", 0,0);
d->status = BURN_DISC_UNSUITABLE;
d->toc_entries = 0;
/* Prefering memory leaks over fandangos */
d->toc_entry = calloc(1, sizeof(struct burn_toc_entry));
return 0;
}
dlen = c.page->data[0] * 256 + c.page->data[1];
old_alloc_len = *alloc_len;
*alloc_len = dlen + 2;
if (old_alloc_len < 12)
return 1;
if (dlen + 2 > old_alloc_len)
dlen = old_alloc_len - 2;
d->complete_sessions = 1 + c.page->data[3] - c.page->data[2];
d->last_track_no = d->complete_sessions;
if (dlen - 2 < (d->last_track_no + 1) * 8) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020159,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
"TOC Format 0 returns inconsistent data", 0,0);
goto err_ex;
}
d->toc_entries = d->last_track_no + d->complete_sessions;
if (d->toc_entries < 1)
return 0;
d->toc_entry = calloc(d->toc_entries, sizeof(struct burn_toc_entry));
if(d->toc_entry == NULL)
return 0;
d->disc = burn_disc_create();
if (d->disc == NULL)
return 0;
for (i = 0; i < d->complete_sessions; i++) {
session = burn_session_create();
if (session == NULL)
return 0;
burn_disc_add_session(d->disc, session, BURN_POS_END);
burn_session_free(session);
}
for (i = 0; i < d->last_track_no; i++) {
tdata = c.page->data + 4 + i * 8;
session_number = i + 1;
if (session_number != prev_session && prev_session > 0) {
/* leadout entry previous session */
entry = &(d->toc_entry[(i - 1) + prev_session]);
lba = mmc_four_char_to_int(start_data) +
mmc_four_char_to_int(size_data);
mmc_int_to_four_char(start_data, lba);
mmc_int_to_four_char(size_data, 0);
mmc_fake_toc_entry(entry, prev_session, 0xA2,
size_data, start_data);
entry->min= entry->sec= entry->frame= 0;
d->disc->session[prev_session - 1]->leadout_entry =
entry;
}
/* ??? >>> d->media_capacity_remaining , d->media_lba_limit
as of mmc_fake_toc()
*/
entry = &(d->toc_entry[i + session_number - 1]);
track = burn_track_create();
if (track == NULL)
return -1;
burn_session_add_track(
d->disc->session[session_number - 1],
track, BURN_POS_END);
track->entry = entry;
burn_track_free(track);
memcpy(start_data, tdata + 4, 4);
/* size_data are estimated from next track start */
memcpy(size_data, tdata + 8 + 4, 4);
size = mmc_four_char_to_int(size_data) -
mmc_four_char_to_int(start_data);
mmc_int_to_four_char(size_data, size);
mmc_fake_toc_entry(entry, session_number, i + 1,
size_data, start_data);
if (prev_session != session_number)
d->disc->session[session_number - 1]->firsttrack = i+1;
d->disc->session[session_number - 1]->lasttrack = i+1;
prev_session = session_number;
}
if (prev_session > 0 && prev_session <= d->disc->sessions) {
/* leadout entry of last session of closed disc */
tdata = c.page->data + 4 + d->last_track_no * 8;
entry = &(d->toc_entry[(d->last_track_no - 1) + prev_session]);
memcpy(start_data, tdata + 4, 4);
mmc_int_to_four_char(size_data, 0);
mmc_fake_toc_entry(entry, prev_session, 0xA2,
size_data, start_data);
entry->min= entry->sec= entry->frame= 0;
d->disc->session[prev_session - 1]->leadout_entry = entry;
}
return 1;
}
/* ts A71128 : for DVD-ROM drives which offer no reliable track information */
static int mmc_read_toc_fmt0(struct burn_drive *d)
{
int alloc_len = 4, ret;
if (mmc_function_spy(d, "mmc_read_toc_fmt0") <= 0)
return -1;
ret = mmc_read_toc_fmt0_al(d, &alloc_len);
if (alloc_len >= 12)
ret = mmc_read_toc_fmt0_al(d, &alloc_len);
return ret;
}
/* ts A70131 : compose a disc TOC structure from d->complete_sessions
and 52h READ TRACK INFORMATION */
int mmc_fake_toc(struct burn_drive *d)
@ -776,6 +960,9 @@ int mmc_fake_toc(struct burn_drive *d)
unsigned char *tdata, size_data[4], start_data[4];
char msg[160];
if (mmc_function_spy(d, "mmc_fake_toc") <= 0)
return -1;
if (d->last_track_no <= 0 || d->complete_sessions <= 0 ||
d->status == BURN_DISC_BLANK)
return 2;
@ -789,6 +976,12 @@ int mmc_fake_toc(struct burn_drive *d)
msg, 0,0);
return 0;
}
/* ts A71128 : My DVD-ROM drive issues no reliable track info.
One has to try 43h READ TOC/PMA/ATIP Form 0. */
if (d->current_profile == 0x10 && d->last_track_no <= 1) {
ret = mmc_read_toc_fmt0(d);
return ret;
}
d->disc = burn_disc_create();
if (d->disc == NULL)
return -1;
@ -799,12 +992,15 @@ int mmc_fake_toc(struct burn_drive *d)
memset(d->toc_entry, 0,d->toc_entries * sizeof(struct burn_toc_entry));
for (i = 0; i < d->complete_sessions; i++) {
session = burn_session_create();
if (session == NULL)
return -1;
burn_disc_add_session(d->disc, session, BURN_POS_END);
burn_session_free(session);
}
memset(size_data, 0, 4);
memset(start_data, 0, 4);
/* Entry Layout :
session 1 track 1 entry 0
...
@ -901,21 +1097,21 @@ static int mmc_read_toc_al(struct burn_drive *d, int *alloc_len)
int i, bpl= 12, old_alloc_len;
unsigned char *tdata;
mmc_function_spy("mmc_read_toc");
if (*alloc_len < 4)
return 0;
if (!(d->current_profile == -1 || d->current_is_cd_profile)) {
/* ts A70131 : MMC_GET_TOC uses Response Format 2
For DVD this fails with 5,24,00 */
/* One could try Response Format 0: mmc5r03.pdf 6.26.3.2
which does not yield the same result wit the same disc
/* mmc_read_toc_fmt0() uses
Response Format 0: mmc5r03.pdf 6.26.3.2
which does not yield the same result with the same disc
on different drives.
*/
/* ts A70201 :
This uses the session count from 51h READ DISC INFORMATION
and the track records from 52h READ TRACK INFORMATION
and the track records from 52h READ TRACK INFORMATION.
mmc_read_toc_fmt0() is used as fallback for dull DVD-ROM.
*/
mmc_fake_toc(d);
@ -955,9 +1151,7 @@ static int mmc_read_toc_al(struct burn_drive *d, int *alloc_len)
d->status = BURN_DISC_UNSUITABLE;
d->toc_entries = 0;
/* Prefering memory leaks over fandangos */
d->toc_entry = malloc(sizeof(struct burn_toc_entry));
memset(&(d->toc_entry[0]), 0, sizeof(struct burn_toc_entry));
d->toc_entry = calloc(1, sizeof(struct burn_toc_entry));
return 0;
}
@ -977,17 +1171,21 @@ static int mmc_read_toc_al(struct burn_drive *d, int *alloc_len)
ts A61007 : if re-enabled then not via Assert.
a ssert(((dlen - 2) % 11) == 0);
*/
d->toc_entry = malloc(d->toc_entries * sizeof(struct burn_toc_entry));
for (i = 0; i < d->toc_entries; i++)
memset(&(d->toc_entry[i]), 0, sizeof(struct burn_toc_entry));
d->toc_entry = calloc(d->toc_entries, sizeof(struct burn_toc_entry));
if(d->toc_entry == NULL) /* ts A70825 */
return 0;
tdata = c.page->data + 4;
burn_print(12, "TOC:\n");
d->disc = burn_disc_create();
if (d->disc == NULL) /* ts A70825 */
return 0;
for (i = 0; i < c.page->data[3]; i++) {
session = burn_session_create();
if (session == NULL) /* ts A70825 */
return 0;
burn_disc_add_session(d->disc, session, BURN_POS_END);
burn_session_free(session);
}
@ -1067,6 +1265,9 @@ void mmc_read_toc(struct burn_drive *d)
{
int alloc_len = 4, ret;
if (mmc_function_spy(d, "mmc_read_toc") <= 0)
return;
ret = mmc_read_toc_al(d, &alloc_len);
/*
fprintf(stderr,
@ -1094,7 +1295,8 @@ int mmc_read_multi_session_c1(struct burn_drive *d, int *trackno, int *start)
struct burn_track **tracks;
struct burn_toc_entry toc_entry;
mmc_function_spy("mmc_read_multi_session_c1");
if (mmc_function_spy(d, "mmc_read_multi_session_c1") <= 0)
return 0;
/* First try to evaluate the eventually loaded TOC before issueing
a MMC command. This search obtains the first track of the last
@ -1181,9 +1383,9 @@ static int mmc_read_disc_info_al(struct burn_drive *d, int *alloc_len)
mmc_get_configuration(d);
/* ts A70910 : found this as condition for mmc_function_spy() which went up
if (*alloc_len < 2)
mmc_function_spy("mmc_read_disc_info");
*/
scsi_init_command(&c, MMC_GET_DISC_INFO, sizeof(MMC_GET_DISC_INFO));
/*
@ -1211,7 +1413,7 @@ static int mmc_read_disc_info_al(struct burn_drive *d, int *alloc_len)
*alloc_len = len + 2;
if (old_alloc_len < 34)
return 1;
if (*alloc_len < 24) /* data[23] is the last byte used her */
if (*alloc_len < 24) /* data[23] is the last byte used here */
return 0;
if (len + 2 > old_alloc_len)
len = old_alloc_len - 2;
@ -1223,6 +1425,7 @@ static int mmc_read_disc_info_al(struct burn_drive *d, int *alloc_len)
disc_status = 2; /* always full and finalized */
d->erasable = 0; /* never erasable */
}
switch (disc_status) {
case 0:
d->toc_entries = 0;
@ -1246,6 +1449,15 @@ static int mmc_read_disc_info_al(struct burn_drive *d, int *alloc_len)
break;
}
/* ts A80207 : DVD +/- R DL can normally be read but not be written */
if((d->current_profile == 0x2b || d->current_profile == 0x15) &&
!d->current_is_supported_profile) {
if(d->status == BURN_DISC_APPENDABLE)
d->status = BURN_DISC_FULL;
d->erasable = 0; /* never erasable */
d->current_is_supported_profile = 1;
}
if ((d->current_profile != 0 || d->status != BURN_DISC_UNREADY)
&& ! d->current_is_supported_profile) {
if (!d->silent_on_scsi_error) {
@ -1281,7 +1493,7 @@ static int mmc_read_disc_info_al(struct burn_drive *d, int *alloc_len)
ts A70112 : same for DVD-RAM
*/
if (d->current_profile == 0x1a || d->current_profile == 0x13 ||
d->current_profile == 0x12)
d->current_profile == 0x12 || d->current_profile == 0x43)
d->status = BURN_DISC_BLANK;
if (d->status == BURN_DISC_BLANK) {
@ -1300,6 +1512,9 @@ static int mmc_read_disc_info_al(struct burn_drive *d, int *alloc_len)
appendable. I.e number of complete tracks + 1. */
d->last_track_no = (data[11] << 8) | data[6];
}
if (d->current_profile != 0x0a && d->current_profile != 0x13 &&
d->current_profile != 0x14 && d->status != BURN_DISC_FULL)
d->erasable = 0; /* stay in sync with burn_disc_erase() */
if (do_read_toc)
mmc_read_toc(d);
@ -1311,6 +1526,9 @@ void mmc_read_disc_info(struct burn_drive *d)
{
int alloc_len = 34, ret;
if (mmc_function_spy(d, "mmc_read_disc_info") <= 0)
return;
ret = mmc_read_disc_info_al(d, &alloc_len);
/*
fprintf(stderr,"LIBBURN_DEBUG: 51h alloc_len = %d , ret = %d\n",
@ -1339,7 +1557,8 @@ void mmc_read_atip(struct burn_drive *d)
4234, 5646, 7056, 8468, -12, -13, -14, -15};
/* 24, 32, 40, 48, -, -, -, - */
mmc_function_spy("mmc_read_atip");
if (mmc_function_spy(d, "mmc_read_atip") <= 0)
return;
scsi_init_command(&c, MMC_GET_ATIP, sizeof(MMC_GET_ATIP));
/*
@ -1495,7 +1714,8 @@ void mmc_read_sectors(struct burn_drive *d,
int errorblock, req;
struct command c;
mmc_function_spy("mmc_read_sectors");
if (mmc_function_spy(d, "mmc_read_sectors") <= 0)
return;
/* ts A61009 : to be ensured by callers */
/* a ssert(len >= 0); */
@ -1564,7 +1784,8 @@ void mmc_erase(struct burn_drive *d, int fast)
{
struct command c;
mmc_function_spy("mmc_erase");
if (mmc_function_spy(d, "mmc_erase") <= 0)
return;
scsi_init_command(&c, MMC_BLANK, sizeof(MMC_BLANK));
/*
@ -1584,7 +1805,9 @@ void mmc_read_lead_in(struct burn_drive *d, struct buffer *buf)
int len;
struct command c;
mmc_function_spy("mmc_read_lead_in");
if (mmc_function_spy(d, "mmc_read_lead_in") <= 0)
return;
len = buf->sectors;
scsi_init_command(&c, MMC_READ_CD, sizeof(MMC_READ_CD));
/*
@ -1610,7 +1833,8 @@ void mmc_perform_opc(struct burn_drive *d)
{
struct command c;
mmc_function_spy("mmc_perform_opc");
if (mmc_function_spy(d, "mmc_perform_opc") <= 0)
return;
scsi_init_command(&c, MMC_SEND_OPC, sizeof(MMC_SEND_OPC));
/*
@ -1640,7 +1864,8 @@ int mmc_set_streaming(struct burn_drive *d,
char msg[160];
unsigned char *pd;
mmc_function_spy("mmc_set_streaming");
if (mmc_function_spy(d, "mmc_set_streaming") <= 0)
return 0;
scsi_init_command(&c, MMC_SET_STREAMING, sizeof(MMC_SET_STREAMING));
/*
@ -1722,7 +1947,8 @@ void mmc_set_speed(struct burn_drive *d, int r, int w)
int ret, end_lba = 0;
struct burn_speed_descriptor *best_sd = NULL;
mmc_function_spy("mmc_set_speed");
if (mmc_function_spy(d, "mmc_set_speed") <= 0)
return;
if (r <= 0 || w <= 0) {
/* ts A70712 : now searching for best speed descriptor */
@ -1842,8 +2068,6 @@ static int mmc_get_configuration_al(struct burn_drive *d, int *alloc_len)
d->current_feat21h_link_size = -1;
d->current_feat2fh_byte4 = -1;
mmc_function_spy("mmc_get_configuration");
scsi_init_command(&c, MMC_GET_CONFIGURATION,
sizeof(MMC_GET_CONFIGURATION));
/*
@ -1883,7 +2107,8 @@ static int mmc_get_configuration_al(struct burn_drive *d, int *alloc_len)
d->current_is_supported_profile = 1;
#endif
#ifdef Libburn_support_dvd_raM
if (cp == 0x12)
if (cp == 0x12 || (cp == 0x43 && burn_support_untested_profiles))
/* DVD-RAM , BD-RE */
d->current_is_supported_profile = 1;
#endif
#ifdef Libburn_support_dvd_r_seQ
@ -1893,8 +2118,7 @@ static int mmc_get_configuration_al(struct burn_drive *d, int *alloc_len)
d->current_is_supported_profile = 1;
#endif
#ifdef Libburn_support_dvd_plus_R
if (cp == 0x1b || (cp == 0x2b && burn_support_untested_profiles))
/* DVD+R , DVD+R/DL */
if (cp == 0x1b || cp == 0x2b) /* DVD+R , DVD+R/DL */
d->current_is_supported_profile = 1;
#endif
@ -2030,6 +2254,9 @@ void mmc_get_configuration(struct burn_drive *d)
{
int alloc_len = 8, ret;
if (mmc_function_spy(d, "mmc_get_configuration") <= 0)
return;
/* first command execution to learn Allocation Length */
ret = mmc_get_configuration_al(d, &alloc_len);
/*
@ -2057,8 +2284,6 @@ static int mmc_read_format_capacities_al(struct burn_drive *d,
char msg[160];
*/
mmc_function_spy("mmc_read_format_capacities");
if (*alloc_len < 4)
return 0;
@ -2195,6 +2420,9 @@ int mmc_read_format_capacities(struct burn_drive *d, int top_wanted)
{
int alloc_len = 4, ret;
if (mmc_function_spy(d, "mmc_read_format_capacities") <= 0)
return 0;
ret = mmc_read_format_capacities_al(d, &alloc_len, top_wanted);
/*
fprintf(stderr,"LIBBURN_DEBUG: 23h alloc_len = %d , ret = %d\n",
@ -2211,7 +2439,8 @@ void mmc_sync_cache(struct burn_drive *d)
{
struct command c;
mmc_function_spy("mmc_sync_cache");
if (mmc_function_spy(d, "mmc_sync_cache") <= 0)
return;
scsi_init_command(&c, MMC_SYNC_CACHE, sizeof(MMC_SYNC_CACHE));
/*
@ -2219,6 +2448,9 @@ void mmc_sync_cache(struct burn_drive *d)
c.oplen = sizeof(MMC_SYNC_CACHE);
*/
c.retry = 1;
c.opcode[1] |= 2; /* ts A70918 : Immed */
c.page = NULL;
c.dir = NO_TRANSFER;
@ -2240,6 +2472,16 @@ void mmc_sync_cache(struct burn_drive *d)
}
d->issue_command(d, &c);
/* ts A70918 */
if (c.error) {
d->cancel = 1;
return;
}
if (spc_wait_unit_attention(d, 3600, "SYNCHRONIZE CACHE", 0) <= 0)
d->cancel = 1;
else
d->needs_sync_cache = 0;
}
@ -2253,7 +2495,8 @@ int mmc_read_buffer_capacity(struct burn_drive *d)
unsigned char *data;
int alloc_len = 12;
mmc_function_spy("mmc_read_buffer_capacity");
if (mmc_function_spy(d, "mmc_read_buffer_capacity") <= 0)
return 0;
scsi_init_command(&c, MMC_READ_BUFFER_CAPACITY,
sizeof(MMC_READ_BUFFER_CAPACITY));
@ -2319,7 +2562,8 @@ int mmc_format_unit(struct burn_drive *d, off_t size, int flag)
char msg[160],descr[80];
int full_format_type = 0x00; /* Full Format (or 0x10 for DVD-RW ?) */
mmc_function_spy("mmc_format_unit");
if (mmc_function_spy(d, "mmc_format_unit") <= 0)
return 0;
scsi_init_command(&c, MMC_FORMAT_UNIT, sizeof(MMC_FORMAT_UNIT));
/*
@ -2552,8 +2796,6 @@ static int mmc_get_write_performance_al(struct burn_drive *d,
/* A61225 : 1 = report about speed descriptors */
static int speed_debug = 0;
mmc_function_spy("mmc_get_write_performance");
if (d->current_profile <= 0)
mmc_get_configuration(d);
@ -2671,6 +2913,9 @@ int mmc_get_write_performance(struct burn_drive *d)
{
int alloc_len = 8, max_descr = 0, ret;
if (mmc_function_spy(d, "mmc_get_write_performance") <= 0)
return 0;
/* first command execution to learn number of descriptors and
dxfer_len */
ret = mmc_get_write_performance_al(d, &alloc_len, &max_descr);
@ -2762,8 +3007,9 @@ int mmc_compose_mode_page_5(struct burn_drive *d,
pd[13] = 16;
} else if (d->current_profile == 0x1a || d->current_profile == 0x1b ||
d->current_profile == 0x2b || d->current_profile == 0x12) {
/* not with DVD+R[W][/DL] or DVD-RAM */;
d->current_profile == 0x2b || d->current_profile == 0x12 ||
d->current_profile == 0x43) {
/* not with DVD+R[W][/DL] or DVD-RAM or BD-RE */;
return 0;
} else {
/* Traditional setup for CD */
@ -2793,6 +3039,48 @@ int mmc_compose_mode_page_5(struct burn_drive *d,
}
/* A70812 ts */
int mmc_read_10(struct burn_drive *d, int start,int amount, struct buffer *buf)
{
struct command c;
if (mmc_function_spy(d, "mmc_read_10") <= 0)
return -1;
;
if (amount > BUFFER_SIZE / 2048)
return -1;
scsi_init_command(&c, MMC_READ_10, sizeof(MMC_READ_10));
c.dxfer_len = amount * 2048;
c.retry = 1;
mmc_int_to_four_char(c.opcode + 2, start);
c.opcode[7] = (amount >> 8) & 0xFF;
c.opcode[8] = amount & 0xFF;
c.page = buf;
c.page->bytes = 0;
c.page->sectors = 0;
c.dir = FROM_DRIVE;
d->issue_command(d, &c);
if (c.error) {
char msg[160];
sprintf(msg,
"SCSI error on read_10(%d,%d): key=%X asc=%2.2Xh ascq=%2.2Xh",
start, amount,
c.sense[2],c.sense[12],c.sense[13]);
if(!d->silent_on_scsi_error)
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020144,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
return BE_CANCELLED;
}
buf->sectors = amount;
buf->bytes = amount * 2048;
return 0;
}
/* ts A61021 : the mmc specific part of sg.c:enumerate_common()
*/
int mmc_setup_drive(struct burn_drive *d)
@ -2815,6 +3103,7 @@ int mmc_setup_drive(struct burn_drive *d)
d->read_buffer_capacity = mmc_read_buffer_capacity;
d->format_unit = mmc_format_unit;
d->read_format_capacities = mmc_read_format_capacities;
d->read_10 = mmc_read_10;
/* ts A70302 */
@ -2835,6 +3124,7 @@ int mmc_setup_drive(struct burn_drive *d)
d->current_feat21h_link_size = -1;
d->current_feat2fh_byte4 = -1;
d->needs_close_session = 0;
d->needs_sync_cache = 0;
d->bg_format_status = -1;
d->num_format_descr = 0;
d->complete_sessions = 0;

View File

@ -68,6 +68,11 @@ 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);
/* mmc5r03c.pdf 4.3.4.4.1 d) "The maximum number of RZones is 2 302." */
#define BURN_MMC_FAKE_TOC_MAX_SIZE 2302

View File

@ -142,6 +142,8 @@ int burn_write_opts_set_simulate(struct burn_write_opts *opts, int sim)
int burn_write_opts_set_underrun_proof(struct burn_write_opts *opts,
int underrun_proof)
{
if (!opts->drive->mdata->valid)
return 0;
if (opts->drive->mdata->underrun_proof) {
opts->underrun_proof = underrun_proof;
return 1;
@ -378,6 +380,13 @@ void burn_write_opts_set_force(struct burn_write_opts *opts, int use_force)
}
/* 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;

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;
/*
#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 */
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;
}
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 = NULL;
d->busy = BURN_DRIVE_IDLE;
return ret;
}

View File

@ -10,6 +10,13 @@
#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 unsigned char SBC_LOAD[] = { 0x1b, 0, 0, 0, 3, 0 };
static unsigned char SBC_UNLOAD[] = { 0x1b, 0, 0, 0, 2, 0 };
@ -19,6 +26,9 @@ 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));
@ -26,24 +36,43 @@ void sbc_load(struct burn_drive *d)
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);
spc_wait_unit_attention(d, 60);
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;
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 = 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 ? */
@ -51,6 +80,9 @@ 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));
@ -58,9 +90,15 @@ int sbc_start_unit(struct burn_drive *d)
c.page = NULL;
*/
c.retry = 1;
c.opcode[1] |= 1; /* ts A70918 : Immed */
c.dir = NO_TRANSFER;
d->issue_command(d, &c);
return (c.error==0);
if (c.error)
return 0;
/* ts A70918 : now asynchronous */
return spc_wait_unit_attention(d, 1800, "START UNIT", 0);
}

View File

@ -123,7 +123,12 @@ 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 <= 0) { /* ts A61031 : extended from (valid == -1) */

View File

@ -48,6 +48,8 @@ sg_issue_command() sends a SCSI command to the drive, receives reply,
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 .
@ -74,6 +76,10 @@ Send feedback to libburn-hackers@pykix.org .
#include <err.h> /* XXX */
/* ts A70909 : >>> untestet yet wether this compiles */
#include <sys/statvfs.h>
/** PORTING : ------ libburn portable headers and definitions ----- */
#include "transport.h"
@ -557,3 +563,69 @@ int sg_is_enumerable_adr(char* adr)
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

@ -18,6 +18,10 @@
#include <err.h> /* XXX */
/* ts A70909 : >>> untestet yet wether this compiles */
#include <sys/statvfs.h>
#include "transport.h"
#include "drive.h"
#include "sg.h"
@ -46,8 +50,9 @@ 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);
/* ts A61021 : Moved most code from scsi_enumerate_drives under
@ -386,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)) {
@ -400,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 ");
}
@ -448,7 +453,8 @@ 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;
if (burn_drive_is_open(d)) {
d->released = 0;
@ -483,14 +489,15 @@ 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;
@ -506,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;
@ -598,3 +605,69 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
return 1;
}
/* 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

@ -48,6 +48,8 @@ sg_issue_command() sends a SCSI command to the drive, receives reply,
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 .
@ -73,6 +75,11 @@ Hint: You should also look into sg-freebsd-port.c, which is a younger and
#include <stdlib.h>
#include <sys/utsname.h>
#include <scsi/scsi.h>
#include <sys/statvfs.h>
/* for ioctl(BLKGETSIZE) */
#include <linux/fs.h>
#include <scsi/sg.h>
/* Values within sg_io_hdr_t indicating success after ioctl(SG_IO) : */
@ -83,6 +90,7 @@ Hint: You should also look into sg-freebsd-port.c, which is a younger and
/* ts A61211 : to eventually recognize CD devices on /dev/sr* */
#include <limits.h>
#include <linux/cdrom.h>
@ -194,8 +202,9 @@ extern int burn_sg_open_abort_busy;
/* 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);
/* ------------------------------------------------------------------------ */
@ -299,6 +308,28 @@ static int sg_close_drive_fd(char *fname, int driveno, int *fd, int sorry)
if(*fd < 0)
return(0);
#ifdef CDROM_MEDIA_CHANGED_disabled_because_not_helpful
#ifdef CDSL_CURRENT
/* ts A80217 : wondering whether the os knows about our activities */
ret = ioctl(*fd, CDROM_MEDIA_CHANGED, CDSL_CURRENT);
sprintf(msg, "ioctl(CDROM_MEDIA_CHANGED) == %d", ret);
libdax_msgs_submit(libdax_messenger, driveno, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
#ifdef BLKFLSBUF_disabled_because_not_helpful
ret = ioctl(*fd, BLKFLSBUF, 0);
sprintf(msg, "ioctl(BLKFLSBUF) == %d", ret);
os_errno = 0;
if(ret == -1)
os_errno = errno;
libdax_msgs_submit(libdax_messenger, driveno, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, msg, os_errno,0);
#endif /* BLKFLSBUF */
#endif /* CDSL_CURRENT */
#endif /* CDROM_MEDIA_CHANGED */
ret = close(*fd);
*fd = -1337;
if(ret != -1) {
@ -932,7 +963,8 @@ int sg_grab(struct burn_drive *d)
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy("sg_grab");
if (mmc_function_spy(d, "sg_grab") <= 0)
return 0;
/* ts A60813 - A60927
@ -960,7 +992,7 @@ int sg_grab(struct burn_drive *d)
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy("sg_grab ----------- opening");
mmc_function_spy(NULL, "sg_grab ----------- opening");
/* ts A70409 : DDLP-B */
/* >>> obtain single lock on d->devname */
@ -1018,7 +1050,8 @@ int sg_release(struct burn_drive *d)
{
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy("sg_release");
if (mmc_function_spy(d, "sg_release") <= 0)
return 0;
if (d->fd < 1) {
burn_print(1, "release an ungrabbed drive. die\n");
@ -1027,7 +1060,7 @@ int sg_release(struct burn_drive *d)
/* ts A60821
<<< debug: for tracing calls which might use open drive fds */
mmc_function_spy("sg_release ----------- closing");
mmc_function_spy(NULL, "sg_release ----------- closing");
sg_close_drive(d);
return 0;
@ -1124,7 +1157,7 @@ int sg_issue_command(struct burn_drive *d, struct command *c)
char buf[161];
sprintf(buf,"sg_issue_command d->fd= %d d->released= %d\n",
d->fd,d->released);
mmc_function_spy(buf);
mmc_function_spy(NULL, buf);
#ifdef Libburn_log_sg_commandS
/* ts A61030 */
@ -1352,3 +1385,60 @@ int sg_is_enumerable_adr(char *adr)
}
/* 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 The pointed value gets modified, but only if an estimation is
possible.
@return -2 = cannot perform necessary operations on file object
-1 = neither path nor dirname of path exist
0 = could not estimate size capacity of file object
1 = estimation has been made, bytes was set
*/
int burn_os_stdio_capacity(char *path, off_t *bytes)
{
struct stat stbuf;
struct statvfs vfsbuf;
char testpath[4096], *cpt;
long blocks;
int open_mode = O_RDONLY, 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;
} else if(S_ISBLK(stbuf.st_mode)) {
fd = open(path, open_mode);
if (fd == -1)
return -2;
ret = ioctl(fd, BLKGETSIZE, &blocks);
close(fd);
if (ret == -1)
return -2;
*bytes = ((off_t) blocks) * (off_t) 512;
} 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

@ -31,4 +31,6 @@ 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,8 +18,6 @@ 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;
@ -34,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*/

View File

@ -27,6 +27,11 @@
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
/* 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 */
/* ts A70519 : allocation length byte 3+4 was 0,255 */
@ -63,6 +68,9 @@ int spc_test_unit_ready_r(struct burn_drive *d, int *key, int *asc, int *ascq)
{
struct command c;
if (mmc_function_spy(d, "test_unit_ready") <= 0)
return 0;
scsi_init_command(&c, SPC_TEST_UNIT_READY,sizeof(SPC_TEST_UNIT_READY));
/*
c.oplen = sizeof(SPC_TEST_UNIT_READY);
@ -90,19 +98,73 @@ int spc_test_unit_ready(struct burn_drive *d)
/* ts A70315 */
/** @param flag bit0=do not wait 0.1 seconds before first test unit ready */
/** Wait until the drive state becomes clear or until max_usec elapsed */
int spc_wait_unit_attention(struct burn_drive *d, int max_sec)
int spc_wait_unit_attention(struct burn_drive *d, int max_sec, char *cmd_text,
int flag)
{
int i, ret, key, asc, ascq;
int i, ret = 1, key = 0, asc = 0, ascq = 0;
char msg[160];
for(i=0; i < max_sec; i++) {
if (!(flag & 1))
usleep(100000);
for(i = !(flag & 1); i < max_sec * 10; i++) {
ret = spc_test_unit_ready_r(d, &key, &asc, &ascq);
if(ret > 0 || key!=0x2 || asc!=0x4) /* ready or error */
/* <<<
fprintf(stderr,
"libburn_EXPERIMENTAL: i= %d ret= %d key= %X asc= %2.2X ascq= %2.2X\n",
i, ret, (unsigned) key, (unsigned) asc, (unsigned) ascq);
*/
if(ret > 0) /* ready */
break;
if(key!=0x2 || asc!=0x4) {
if (key == 0x2 && asc == 0x3A) {
ret = 1; /* medium not present = ok */
/* <<<
ts A70912 :
My LG GSA-4082B on asynchronous load:
first it reports no media 2,3A,00,
then it reports not ready 2,04,00,
further media inquiry retrieves wrong data
if(i<=100)
goto slumber;
*/
break;
usleep(1000000);
}
if (i < max_sec)
if (key == 0x6 && asc == 0x28 && ascq == 0x00)
/* media change notice = try again */
goto slumber;
sprintf(msg,
"Asynchromous SCSI error on %s: key=%X asc=%2.2Xh ascq=%2.2Xh",
cmd_text, (unsigned) key, (unsigned) asc,
(unsigned) ascq);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002014d,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
d->cancel = 1;
break;
}
slumber:;
usleep(100000);
}
sprintf(msg, "Async %s %s after %d.%d seconds",
cmd_text, (ret > 0 ? "succeeded" : "failed"), i / 10, i % 10);
libdax_msgs_submit(libdax_messenger, d->global_index, 0x00020150,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_LOW, msg, 0, 0);
if (i < max_sec * 10)
return (ret > 0);
sprintf(msg, "Timeout (%d s) with asynchronous SCSI command %s\n",
max_sec, cmd_text);
libdax_msgs_submit(libdax_messenger, d->global_index, 0x0002014f,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
return 0;
}
@ -111,6 +173,9 @@ void spc_request_sense(struct burn_drive *d, struct buffer *buf)
{
struct command c;
if (mmc_function_spy(d, "request_sense") <= 0)
return;
scsi_init_command(&c, SPC_REQUEST_SENSE, sizeof(SPC_REQUEST_SENSE));
c.retry = 0;
/*
@ -130,6 +195,9 @@ int spc_get_erase_progress(struct burn_drive *d)
{
struct buffer b;
if (mmc_function_spy(d, "get_erase_progress") <= 0)
return 0;
spc_request_sense(d, &b);
return (b.data[16] << 8) | b.data[17];
}
@ -140,6 +208,9 @@ void spc_inquiry(struct burn_drive *d)
struct burn_scsi_inquiry_data *id;
struct command c;
if (mmc_function_spy(d, "inquiry") <= 0)
return;
scsi_init_command(&c, SPC_INQUIRY, sizeof(SPC_INQUIRY));
/*
memcpy(c.opcode, SPC_INQUIRY, sizeof(SPC_INQUIRY));
@ -171,6 +242,9 @@ void spc_prevent(struct burn_drive *d)
{
struct command c;
if (mmc_function_spy(d, "prevent") <= 0)
return;
scsi_init_command(&c, SPC_PREVENT, sizeof(SPC_PREVENT));
/*
memcpy(c.opcode, SPC_PREVENT, sizeof(SPC_PREVENT));
@ -186,6 +260,9 @@ void spc_allow(struct burn_drive *d)
{
struct command c;
if (mmc_function_spy(d, "allow") <= 0)
return;
scsi_init_command(&c, SPC_ALLOW, sizeof(SPC_ALLOW));
/*
memcpy(c.opcode, SPC_ALLOW, sizeof(SPC_ALLOW));
@ -368,6 +445,9 @@ void spc_sense_caps(struct burn_drive *d)
{
int alloc_len, start_len = 22, ret;
if (mmc_function_spy(d, "sense_caps") <= 0)
return;
/* first command execution to learn Allocation Length */
alloc_len = start_len;
ret = spc_sense_caps_al(d, &alloc_len, 1);
@ -389,6 +469,9 @@ void spc_sense_error_params(struct burn_drive *d)
unsigned char *page;
struct command c;
if (mmc_function_spy(d, "sense_error_params") <= 0)
return;
scsi_init_command(&c, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE));
/*
memcpy(c.opcode, SPC_MODE_SENSE, sizeof(SPC_MODE_SENSE));
@ -419,6 +502,9 @@ void spc_select_error_params(struct burn_drive *d,
struct buffer buf;
struct command c;
if (mmc_function_spy(d, "select_error_params") <= 0)
return;
scsi_init_command(&c, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT));
/*
memcpy(c.opcode, SPC_MODE_SELECT, sizeof(SPC_MODE_SELECT));
@ -457,6 +543,9 @@ void spc_sense_write_params(struct burn_drive *d)
unsigned char *page;
struct command c;
if (mmc_function_spy(d, "sense_write_params") <= 0)
return;
/* ts A61007 : Done in soft at only caller burn_drive_grab() */
/* a ssert(d->mdata->cdr_write || d->mdata->cdrw_write ||
d->mdata->dvdr_write || d->mdata->dvdram_write); */
@ -477,17 +566,21 @@ void spc_sense_write_params(struct burn_drive *d)
c.dir = FROM_DRIVE;
d->issue_command(d, &c);
size = c.page->data[0] * 256 + c.page->data[1];
/* ts A71128 : do not interpret reply if error */
m = d->mdata;
if(!c.error) {
size = c.page->data[0] * 256 + c.page->data[1];
page = c.page->data + 8;
burn_print(1, "write page length 0x%x\n", page[1]);
m->write_page_length = page[1];
m->write_page_valid = 1;
} else
m->write_page_valid = 0;
mmc_read_disc_info(d);
/* ts A70212 : try to setup d->media_capacity_remaining */
if (d->current_profile == 0x1a || d->current_profile == 0x13 ||
d->current_profile == 0x12)
d->current_profile == 0x12 || d->current_profile == 0x43)
d->read_format_capacities(d, -1);
else if (d->status == BURN_DISC_BLANK ||
(d->current_is_cd_profile && d->status == BURN_DISC_APPENDABLE)) {
@ -514,6 +607,9 @@ void spc_select_write_params(struct burn_drive *d,
struct buffer buf;
struct command c;
if (mmc_function_spy(d, "select_write_params") <= 0)
return;
/* ts A61007 : All current callers are safe. */
/* a ssert(o->drive == d); */
@ -554,6 +650,9 @@ void spc_select_write_params(struct burn_drive *d,
void spc_getcaps(struct burn_drive *d)
{
if (mmc_function_spy(d, "getcaps") <= 0)
return;
spc_inquiry(d);
spc_sense_caps(d);
spc_sense_error_params(d);
@ -573,6 +672,9 @@ void spc_probe_write_modes(struct burn_drive *d)
int last_try = 0;
struct command c;
if (mmc_function_spy(d, "spc_probe_write_modes") <= 0)
return;
/* ts A70213 : added pseudo try_write_type 4 to set a suitable mode */
while (try_write_type != 5) {
burn_print(9, "trying %d, %d\n", try_write_type,
@ -739,11 +841,8 @@ int burn_scsi_setup_drive(struct burn_drive *d, int bus_no, int host_no,
d->silent_on_scsi_error = 0;
d->idata = malloc(sizeof(struct burn_scsi_inquiry_data));
d->idata->valid = 0;
d->mdata = malloc(sizeof(struct scsi_mode_data));
d->mdata->valid = 0;
d->mdata->speed_descriptors = NULL;
d->idata = calloc(1, sizeof(struct burn_scsi_inquiry_data));
d->mdata = calloc(1, sizeof(struct scsi_mode_data));
/* ts A61007 : obsolete Assert in drive_getcaps() */
if(d->idata == NULL || d->mdata == NULL) {
@ -752,6 +851,9 @@ int burn_scsi_setup_drive(struct burn_drive *d, int bus_no, int host_no,
"Could not allocate new drive object", 0, 0);
return -1;
}
d->idata->valid = 0;
d->mdata->valid = 0;
d->mdata->speed_descriptors = NULL;
if(!(flag & 1)) {
ret = spc_setup_drive(d);
if (ret<=0)

View File

@ -28,7 +28,8 @@ 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);
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()
*/

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;
@ -104,6 +108,8 @@ 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;

View File

@ -114,13 +114,21 @@ struct burn_format_descr {
off_t size;
/* the Type Dependent Parameter (usually the write alignment size) */
unsigned tdp;
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;
@ -172,9 +180,12 @@ struct burn_drive
*/
int current_feat2fh_byte4;
/* ts A70114 : wether a DVD-RW media holds an incomplete session
/* 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 A61218 from 51h READ DISC INFORMATION */
int bg_format_status; /* 0=needs format start, 1=needs format restart*/
@ -182,7 +193,7 @@ struct burn_drive
/* 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 format_curr_blsas; /* meaning depends on format_descr_type */
unsigned int format_curr_blsas; /* dito */
int best_format_type;
off_t best_format_size;
@ -196,6 +207,8 @@ struct burn_drive
/* 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 */
@ -229,18 +242,24 @@ struct burn_drive
int pbf_altered;
int wait_for_buffer_free;
int nominal_write_speed;
unsigned wfb_min_usec;
unsigned wfb_max_usec;
unsigned wfb_timeout_sec;
unsigned wfb_min_percent;
unsigned wfb_max_percent;
unsigned pessimistic_writes;
unsigned waited_writes;
unsigned waited_tries;
unsigned waited_usec;
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 *);
@ -320,6 +339,11 @@ struct burn_drive
/* 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 */

View File

@ -47,7 +47,14 @@ char *burn_strndup(char *s, int n)
void burn_version(int *major, int *minor, int *micro)
{
/* ts A80408 : switched from configure.ac versioning to libburn.h versioning */
#ifdef burn_header_version_major
*major = burn_header_version_major;
*minor = burn_header_version_minor;
*micro = burn_header_version_micro;
#else
*major = BURN_MAJOR_VERSION;
*minor = BURN_MINOR_VERSION;
*micro = BURN_MICRO_VERSION;
#endif
}

View File

@ -18,11 +18,16 @@
#define Libburn_sao_can_appenD 1
*/
#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <ctype.h>
#include <stdlib.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/stat.h>
#include <sys/time.h>
#include "error.h"
#include "sector.h"
#include "libburn.h"
@ -38,6 +43,7 @@
#include "write.h"
#include "options.h"
#include "structure.h"
#include "source.h"
#include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger;
@ -112,7 +118,9 @@ void type_to_form(int mode, unsigned char *ctladr, int *form)
*form |= 0x40;
}
int burn_write_flush(struct burn_write_opts *o, struct burn_track *track)
/* ts A71002 : outsourced from burn_write_flush() : no sync cache here */
int burn_write_flush_buffer(struct burn_write_opts *o,struct burn_track *track)
{
struct burn_drive *d = o->drive;
@ -133,13 +141,25 @@ int burn_write_flush(struct burn_write_opts *o, struct burn_track *track)
d->buffer->bytes = 0;
d->buffer->sectors = 0;
}
return 1;
}
int burn_write_flush(struct burn_write_opts *o, struct burn_track *track)
{
int ret;
struct burn_drive *d = o->drive;
ret = burn_write_flush_buffer(o, track);
if (ret <= 0)
return ret;
d->sync_cache(d);
return 1;
}
/* ts A61030 */
int burn_write_close_track(struct burn_write_opts *o, struct burn_session *s,
/* ts A71002 : outsourced from burn_write_close_track() */
int burn_write_track_minsize(struct burn_write_opts *o, struct burn_session *s,
int tnum)
{
char msg[81];
@ -147,11 +167,6 @@ int burn_write_close_track(struct burn_write_opts *o, struct burn_session *s,
struct burn_track *t;
int todo, step, cancelled, seclen;
/* ts A61106 */
#ifdef Libburn_experimental_no_close_tracK
return 1;
#endif
d = o->drive;
t = s->track[tnum];
@ -185,8 +200,26 @@ int burn_write_close_track(struct burn_write_opts *o, struct burn_session *s,
}
d->cancel = cancelled;
}
return 1;
}
/* ts A61030 */
int burn_write_close_track(struct burn_write_opts *o, struct burn_session *s,
int tnum)
{
char msg[81];
struct burn_drive *d;
struct burn_track *t;
/* ts A61106 */
#ifdef Libburn_experimental_no_close_tracK
return 1;
#endif
d = o->drive;
t = s->track[tnum];
/* ts A61102 */
d->busy = BURN_DRIVE_CLOSING_TRACK;
sprintf(msg, "Closing track %2.2d", tnum+1);
@ -201,13 +234,13 @@ int burn_write_close_track(struct burn_write_opts *o, struct burn_session *s,
*/
d->close_track_session(o->drive, 0, 0xff);
/* ts A61102 */
d->busy = BURN_DRIVE_WRITING;
return 1;
}
/* ts A61030 */
int burn_write_close_session(struct burn_write_opts *o, struct burn_session *s)
{
@ -804,14 +837,18 @@ int burn_write_track(struct burn_write_opts *o, struct burn_session *s,
/* ts A61103 */
ret = 1;
ex:;
if (d->cancel)
burn_source_cancel(t->source);
if (o->write_type == BURN_WRITE_TAO) {
/* ts A61103 */
/* >>> if cancelled: ensure that at least 600 kB get written */
if (!burn_write_flush(o, t))
/* ts A71002 */
if (!burn_write_flush_buffer(o, t))
ret = 0;
/* Ensure that at least 600 kB get written */
burn_write_track_minsize(o, s, tnum);
d->sync_cache(d);
/* ts A61030 */
if (burn_write_close_track(o, s, tnum) <= 0)
ret = 0;
@ -910,6 +947,13 @@ int burn_precheck_write(struct burn_write_opts *o, struct burn_disc *disc,
reason_pt= reasons;
reasons[0] = 0;
if (d->drive_role == 0) {
sprintf(reasons,
"DRIVE: is a virtual placeholder (null-drive)");
no_media = 1;
goto ex;
}
/* check write mode against write job */
wt = burn_write_opts_auto_write_type(o, disc, reasons, 1);
if (wt == BURN_WRITE_NONE) {
@ -922,25 +966,29 @@ int burn_precheck_write(struct burn_write_opts *o, struct burn_disc *disc,
reason_pt= reasons + strlen(reasons);
if (d->status == BURN_DISC_UNSUITABLE)
goto unsuitable_profile;
if (d->current_profile == 0x09 || d->current_profile == 0x0a) {
if (d->drive_role == 2 ||
d->current_profile == 0x1a || d->current_profile == 0x12 ||
d->current_profile == 0x43) {
/* DVD+RW , DVD-RAM , BD-RE, emulated drive on stdio file */
if (o->start_byte >= 0 && (o->start_byte % 2048))
strcat(reasons,
"write start address not properly aligned to 2048, ");
} else if (d->current_profile == 0x09 || d->current_profile == 0x0a) {
/* CD-R , CD-RW */
if (!burn_disc_write_is_ok(o, disc, (!!silent) << 1))
strcat(reasons, "unsuitable track mode found, ");
if (o->start_byte >= 0)
strcat(reasons, "write start address not supported, ");
} else if (d->current_profile == 0x1a || d->current_profile == 0x12) {
/* DVD+RW , DVD-RAM */
if (o->start_byte >= 0 && (o->start_byte % 2048))
strcat(reasons,
"write start address not properly aligned to 2048, ");
} else if (d->current_profile == 0x13) {
/* DVD-RW Restricted Overwrite */
if (o->start_byte >= 0 && (o->start_byte % 32768))
strcat(reasons,
"write start address not properly aligned to 32k, ");
} else if (d->current_profile == 0x11 || d->current_profile == 0x14 ||
} else if (d->drive_role == 3 ||
d->current_profile == 0x11 || d->current_profile == 0x14 ||
d->current_profile == 0x15 ||
d->current_profile == 0x1b || d->current_profile == 0x2b ) {
/* DVD-R* Sequential , DVD+R[/DL] */
/* DVD-R* Sequential , DVD+R[/DL] , sequential stdio "drive" */
if (o->start_byte >= 0)
strcat(reasons, "write start address not supported, ");
} else {
@ -1177,7 +1225,7 @@ int burn_dvd_write_track(struct burn_write_opts *o,
}
/* >>> ts A70215 : what about offset padding ? */
/* (offset padding is done within sector_data()) */
burn_disc_init_track_status(o, s, tnum, sectors);
for (i = 0; open_ended || i < sectors; i++) {
@ -1200,7 +1248,7 @@ int burn_dvd_write_track(struct burn_write_opts *o,
d->progress.sector++;
}
/* >>> ts A70215 : what about tail padding ? */
/* (tail padding is done in sector_data()) */
/* Pad up buffer to next full o->obs (usually 32 kB) */
if (o->obs_pad && out->bytes > 0 && out->bytes < o->obs) {
@ -1229,6 +1277,8 @@ int burn_dvd_write_track(struct burn_write_opts *o,
}
ret = 1;
ex:;
if (d->cancel)
burn_source_cancel(t->source);
if (!is_flushed)
d->sync_cache(d); /* burn_write_flush() was not called */
return ret;
@ -1321,8 +1371,8 @@ int burn_dvd_write_session(struct burn_write_opts *o,
ret = burn_disc_close_session_dvd_minus_r(o, s);
if (ret <= 0)
return 0;
} else if (d->current_profile == 0x12) {
/* DVD-RAM */
} else if (d->current_profile == 0x12 || d->current_profile == 0x43) {
/* DVD-RAM , BD-RE */
/* ??? any finalization needed ? */;
} else if (d->current_profile == 0x13) {
/* DVD-RW restricted overwrite */
@ -1431,8 +1481,6 @@ int burn_disc_setup_dvd_minus_rw(struct burn_write_opts *o,
/* >>> perform OPC if needed */;
/* >>> */;
return 1;
}
@ -1473,63 +1521,11 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
struct burn_track *t;
char msg[160];
#ifndef Libburn_precheck_write_ruleS
int exotic_track = 0, dao_is_ok, sx, tx, mode;
#endif
d->needs_close_session = 0;
#ifndef Libburn_precheck_write_ruleS
/* <<< covered by burn_precheck_write() */
for (sx = 0; sx < disc->sessions; sx++)
for (tx = 0 ; tx < disc->session[sx]->tracks; tx++) {
mode = disc->session[sx]->track[tx]->mode;
if (disc->session[sx]->track[tx]->mode != BURN_MODE1)
exotic_track = 1;
}
if (exotic_track) {
sprintf(msg,"DVD Media are unsuitable for desired track type");
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020123,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
goto early_failure;
}
/* <<< covered by burn_precheck_write() */
if (d->current_profile == 0x1a || d->current_profile == 0x13 ||
d->current_profile == 0x12) {
/* DVD+RW , DVD-RW Restricted Overwrite , DVD-RAM */
if (disc->sessions!=1 || disc->session[0]->tracks>1
|| o->multi ) {
sprintf(msg,
"Burning is restricted to a single track and no multi-session on %s",
d->current_profile_text);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002011f,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
goto early_failure;
}
}
#endif /* ! Libburn_precheck_write_ruleS */
if (d->current_profile == 0x1a || d->current_profile == 0x12) {
/* DVD+RW , DVD-RAM */
#ifndef Libburn_precheck_write_ruleS
/* <<< covered by burn_precheck_write() */
if (o->start_byte >= 0 && (o->start_byte % 2048)) {
sprintf(msg,
"Write start address not properly aligned to 2048");
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020125,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
goto early_failure;
}
#endif /* ! Libburn_precheck_write_ruleS */
if (d->current_profile == 0x1a || d->current_profile == 0x12 ||
d->current_profile == 0x43) {
/* DVD+RW , DVD-RAM , BD-RE */
ret = 1;
if (d->current_profile == 0x1a)
ret = burn_disc_setup_dvd_plus_rw(o, disc);
@ -1546,20 +1542,6 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
} else if (d->current_profile == 0x13) {
/* DVD-RW Restricted Overwrite */
#ifndef Libburn_precheck_write_ruleS
/* <<< covered by burn_precheck_write() */
if (o->start_byte >= 0 && (o->start_byte % 32768)) {
sprintf(msg,
"Write start address not properly aligned to 32K");
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020125,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
goto early_failure;
}
#endif /* ! Libburn_precheck_write_ruleS */
ret = burn_disc_setup_dvd_minus_rw(o, disc);
if (ret <= 0) {
sprintf(msg,
@ -1580,69 +1562,6 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
t = disc->session[0]->track[0];
o_end = ( burn_track_is_open_ended(t) && !o->fill_up_media );
default_size = burn_track_get_default_size(t);
#ifndef Libburn_precheck_write_ruleS
dao_is_ok =
(disc->sessions == 1 &&
disc->session[0]->tracks == 1 &&
(default_size > 0 || !o_end) &&
(!o->multi) && d->status == BURN_DISC_BLANK
);
if (o->write_type == BURN_WRITE_TAO &&
!d->current_has_feat21h) {
/* <<< ??? keep this automatic write type change ? */
if (dao_is_ok) {
o->write_type = BURN_WRITE_SAO;
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x00020134,
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
"Defaulted TAO to DAO (lack of feature 21h)",
0, 0);
/* <<< covered by burn_precheck_write() */
} else {
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x00020135,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Cannot perform TAO (lack of feature 21h), job unsuitable for DAO",
0, 0);
goto early_failure;
}
} else if (o->write_type == BURN_WRITE_SAO && !dao_is_ok) {
/* <<< covered by burn_precheck_write() */
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020136,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"DAO burning is restricted to a single fixed size track and no multi-session",
0, 0);
/* <<< ??? keep this automatic advise ? */
if (d->current_has_feat21h)
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x00020137,
LIBDAX_MSGS_SEV_HINT,
LIBDAX_MSGS_PRIO_HIGH,
"TAO would be possible and could do the job",
0, 0);
goto early_failure;
}
/* <<< covered by burn_precheck_write() */
if (o->start_byte >= 0) {
sprintf(msg, "Write start address not supported");
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020124,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
goto early_failure;
}
#endif /* ! Libburn_precheck_write_ruleS */
if (o->write_type == BURN_WRITE_SAO && o_end) {
sprintf(msg, "Activated track default size %.f",
(double) default_size);
@ -1670,11 +1589,6 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
t = disc->session[0]->track[0];
o_end = ( burn_track_is_open_ended(t) && !o->fill_up_media );
default_size = burn_track_get_default_size(t);
#ifndef Libburn_precheck_write_ruleS
/* >>> oldfashioned checks hopefully never re-enabled */
#endif /* ! Libburn_precheck_write_ruleS */
if (o->write_type == BURN_WRITE_SAO && o_end) {
sprintf(msg, "Activated track default size %.f",
(double) default_size);
@ -1696,19 +1610,6 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
}
/* ??? padding needed ??? cowardly doing it for now */
o->obs_pad = 1; /* fill-up track's last 32k buffer */
#ifndef Libburn_precheck_write_ruleS
/* <<< covered by burn_precheck_write() */
} else {
sprintf(msg, "Unsuitable media detected. Profile %4.4Xh %s",
d->current_profile, d->current_profile_text);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002011e,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
goto early_failure;
#endif /* ! Libburn_precheck_write_ruleS */
}
o->obs = 32*1024; /* buffer flush trigger for sector.c:get_sector() */
@ -1743,6 +1644,323 @@ early_failure:;
}
/* ts A70904 */
int burn_stdio_open_write(struct burn_drive *d, off_t start_byte,
int sector_size, int flag)
{
/* <<< We need _LARGEFILE64_SOURCE defined by the build system.
*/
#ifndef O_LARGEFILE
#define O_LARGEFILE 0
#endif
int fd = -1;
int mode = O_RDWR | O_CREAT | O_LARGEFILE;
char msg[160];
if (d->devname[0] == 0) /* null drives should not come here */
return -1;
fd = burn_drive__fd_from_special_adr(d->devname);
if (fd >= 0)
fd = dup(fd); /* check validity and make closeable */
else
fd = open(d->devname, mode, S_IRUSR | S_IWUSR);
if (fd == -1) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020005,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Failed to open device (a pseudo-drive)", errno, 0);
d->cancel = 1;
return -1;
}
if (start_byte < 0)
start_byte = 0;
if (d->drive_role == 2)
if (lseek(fd, start_byte, SEEK_SET)==-1) {
sprintf(msg, "Cannot address start byte %.f",
(double) start_byte);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020147,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, errno, 0);
close(fd);
d->cancel = 1;
fd = -1;
}
d->nwa = start_byte / sector_size;
return fd;
}
/* ts A70904 */
int burn_stdio_read_source(struct burn_source *source, char *buf, int bufsize,
struct burn_write_opts *o, int flag)
{
int count= 0, todo;
for(todo = bufsize; todo > 0; todo -= count) {
if(source->read!=NULL)
count = source->read(source,
(unsigned char *) (buf + (bufsize - todo)), todo);
else
count = source->read_xt(source,
(unsigned char *) (buf + (bufsize - todo)), todo);
if (count <= 0)
break;
}
return (bufsize - todo);
}
/* ts A70904 */
int burn_stdio_write(int fd, char *buf, int count, struct burn_drive *d,
int flag)
{
if (write(fd, buf, count) != count) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020148,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Cannot write desired amount of data", errno, 0);
d->cancel = 1;
return 0;
}
return count;
}
/* ts A70910 : to be used as burn_drive.write(), emulating mmc_write() */
int burn_stdio_mmc_write(struct burn_drive *d, int start, struct buffer *buf)
{
int ret;
off_t start_byte;
if (d->cancel)
return BE_CANCELLED;
if (d->stdio_fd < 0) {
/* >>> program error */;
d->cancel = 1;
return BE_CANCELLED;
}
if (start != d->nwa) {
char msg[80];
start_byte = ((off_t) start) *
(off_t) (buf->bytes / buf->sectors);
if (lseek(d->stdio_fd, start_byte, SEEK_SET)==-1) {
sprintf(msg, "Cannot address start byte %.f",
(double) start_byte);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020147,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, errno, 0);
d->cancel = 1;
return BE_CANCELLED;
}
d->nwa = start;
}
ret = burn_stdio_write(d->stdio_fd,(char *)buf->data, buf->bytes, d,0);
if (ret <= 0)
return BE_CANCELLED;
d->nwa += buf->sectors;
return 0;
}
/* ts A70910 : to be used as burn_drive.write(),
emulating mmc_write() with simulated writing. */
int burn_stdio_mmc_dummy_write(struct burn_drive *d, int start,
struct buffer *buf)
{
if (d->cancel)
return BE_CANCELLED;
d->nwa = start + buf->sectors;
return 0;
}
/* ts A70911 */
/* Flush stdio system buffer to physical device.
@param flag bit0= do not report debug message (intermediate sync)
*/
int burn_stdio_sync_cache(int fd, struct burn_drive *d, int flag)
{
if (fd < 0) {
/* >>> program error */;
d->cancel = 1;
return 0;
}
d->needs_sync_cache = 0;
if (!(flag & 1))
libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
"syncing cache (stdio fsync)", 0, 0);
if (fsync(fd) != 0) {
if (errno == EINVAL) /* E.g. /dev/null cannot fsync */
return 1;
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020148,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Cannot write desired amount of data", errno, 0);
d->cancel = 1;
return 0;
}
return 1;
}
/* ts A70911 : to be used as burn_drive.sync_cache(),
emulating mmc_sync_cache() */
void burn_stdio_mmc_sync_cache(struct burn_drive *d)
{
burn_stdio_sync_cache(d->stdio_fd, d, 0);
}
/* ts A70912 */
/* Enforces eventual nominal write speed.
@param flag bit0= initialize *prev_time */
int burn_stdio_slowdown(struct burn_drive *d, struct timeval *prev_time,
int amount, int flag)
{
struct timeval tnow;
struct timezone dummy_tz;
double to_wait;
if (flag & 1) {
gettimeofday(prev_time, &dummy_tz);
return 1;
}
if(d->nominal_write_speed <= 0)
return 2;
gettimeofday(&tnow, &dummy_tz);
to_wait = ( ((double) amount) / (double) d->nominal_write_speed ) -
(double) ( tnow.tv_sec - prev_time->tv_sec ) -
(double) ( tnow.tv_usec - prev_time->tv_usec ) / 1.0e6
- 0.001; /* best would be 1 / kernel granularity HZ */
if (to_wait >= 0.0001) {
usleep((int) (to_wait * 1000000.0));
}
gettimeofday(prev_time, &dummy_tz);
return 1;
}
/* ts A70904 */
int burn_stdio_write_track(struct burn_write_opts *o, struct burn_session *s,
int tnum, int flag)
{
int open_ended, bufsize, ret, sectors, fd;
struct burn_track *t = s->track[tnum];
struct burn_drive *d = o->drive;
char buf[16*2048];
int i, prev_sync_sector = 0;
struct buffer *out = d->buffer;
struct timeval prev_time;
bufsize = sizeof(buf);
fd = d->stdio_fd;
sectors = burn_track_get_sectors(t);
burn_disc_init_track_status(o, s, tnum, sectors);
open_ended = burn_track_is_open_ended(t);
/* attach stdio emulators for mmc_*() functions */
if (o->simulate)
d->write = burn_stdio_mmc_dummy_write;
else
d->write = burn_stdio_mmc_write;
d->sync_cache = burn_stdio_mmc_sync_cache;
burn_stdio_slowdown(d, &prev_time, 0, 1); /* initialize */
for (i = 0; open_ended || i < sectors; i++) {
/* transact a (CD sized) sector */
if (!sector_data(o, t, 0))
{ret= 0; goto ex;}
if (open_ended) {
d->progress.sectors = sectors = d->progress.sector;
if (burn_track_is_data_done(t))
break;
}
d->progress.sector++;
/* Flush to disk after each full MB */
if (d->progress.sector - prev_sync_sector >= 512) {
prev_sync_sector = d->progress.sector;
if (!o->simulate)
burn_stdio_sync_cache(d->stdio_fd, d, 1);
burn_stdio_slowdown(d, &prev_time, 512 * 2, 0);
}
}
/* Pad up buffer to next full o->obs (usually 32 kB) */
if (o->obs_pad && out->bytes > 0 && out->bytes < o->obs) {
memset(out->data + out->bytes, 0, o->obs - out->bytes);
out->sectors += (o->obs - out->bytes) / 2048;
out->bytes = o->obs;
}
ret = burn_write_flush(o, t);
ret= 1;
ex:;
if (d->cancel)
burn_source_cancel(t->source);
return ret;
}
/* ts A70904 */
int burn_stdio_write_sync(struct burn_write_opts *o,
struct burn_disc *disc)
{
int ret;
struct burn_drive *d = o->drive;
d->needs_close_session = 0;
o->obs_pad = 0; /* no filling-up of track's last 32k buffer */
o->obs = 32*1024; /* buffer size */
if (disc->sessions != 1)
{ret= 0 ; goto ex;}
if (disc->session[0]->tracks != 1)
{ret= 0 ; goto ex;}
/* update progress */
d->progress.session = 0;
d->progress.tracks = 1;
/* >>> adjust sector size (2048) to eventual audio or even raw */
/* open target file */
if (d->stdio_fd >= 0)
close(d->stdio_fd);
d->stdio_fd = burn_stdio_open_write(d, o->start_byte, 2048, 0);
if (d->stdio_fd == -1)
{ret = 0; goto ex;}
ret = burn_stdio_write_track(o, disc->session[0], 0, 0);
if (ret <= 0)
goto ex;
/* XXX: currently signs an end of session */
d->progress.sector = 0;
d->progress.start_sector = 0;
d->progress.sectors = 0;
ret = 1;
ex:;
if (d->stdio_fd >= 0)
close(d->stdio_fd);
d->stdio_fd = -1;
/* update media state records */
burn_drive_mark_unready(d);
d->busy = BURN_DRIVE_IDLE;
return ret;
}
void burn_disc_write_sync(struct burn_write_opts *o, struct burn_disc *disc)
{
struct cue_sheet *sheet;
@ -1765,6 +1983,13 @@ void burn_disc_write_sync(struct burn_write_opts *o, struct burn_disc *disc)
d->rlba = -150;
d->toc_temp = 9;
/* ts A70904 */
if (d->drive_role != 1) {
ret = burn_stdio_write_sync(o, disc);
if (ret <= 0)
goto fail_wo_sync;
return;
}
/* ts A61218 */
if (! d->current_is_cd_profile) {
ret = burn_dvd_write_sync(o, disc);
@ -1773,45 +1998,12 @@ void burn_disc_write_sync(struct burn_write_opts *o, struct burn_disc *disc)
return;
}
#ifndef Libburn_precheck_write_ruleS
/* <<< covered by burn_precheck_write() */
if (o->start_byte >= 0) {
sprintf(msg, "Write start address not supported");
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020124,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
goto fail_wo_sync;
}
#endif /* ! Libburn_precheck_write_ruleS */
/* ts A70218 */
if (o->write_type == BURN_WRITE_SAO) {
#ifndef Libburn_precheck_write_ruleS
/* <<< covered by burn_precheck_write() "appended session" */
if (disc->sessions > 1) {
sao_restriction_violated:;
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002012f,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"SAO is restricted to a single session with fixed track sizes",
0, 0);
goto fail_wo_sync;
}
#endif /* ! Libburn_precheck_write_ruleS */
for (i = 0 ; i < disc->session[0]->tracks; i++) {
t = disc->session[0]->track[i];
if (burn_track_is_open_ended(t)) {
default_size = burn_track_get_default_size(t);
#ifndef Libburn_precheck_write_ruleS
/* <<< covered by burn_precheck_write() */
if (default_size <= 0)
goto sao_restriction_violated;
#endif /* ! Libburn_precheck_write_ruleS */
sprintf(msg,
"Activated track default size %.f",
(double) default_size);
@ -1969,3 +2161,126 @@ fail_wo_sync:;
d->cancel = 1;
d->busy = BURN_DRIVE_IDLE;
}
/* ts A70811 : API function */
int burn_random_access_write(struct burn_drive *d, off_t byte_address,
char *data, off_t data_count, int flag)
{
int alignment = 0, start, upto, chunksize, err, fd = -1, ret;
char msg[81], *rpt;
struct buffer buf;
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 write", 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;
}
if(d->drive_role == 2)
alignment = 2 * 1024;
if (d->current_profile == 0x12) /* DVD-RAM */
alignment = 2 * 1024;
if (d->current_profile == 0x13) /* DVD-RW restricted overwrite */
alignment = 32 * 1024;
if (d->current_profile == 0x1a) /* DVD+RW */
alignment = 2 * 1024;
if (d->current_profile == 0x43) /* BD-RE */
alignment = 2 * 1024;
if (alignment == 0) {
sprintf(msg, "Write start address not supported");
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020125,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
"Write start address not supported", 0, 0);
return 0;
}
if ((byte_address % alignment) != 0) {
sprintf(msg,
"Write start address not properly aligned (%d bytes)",
alignment);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020126,
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
return 0;
}
if ((data_count % alignment) != 0) {
sprintf(msg,
"Write data count not properly aligned (%ld bytes)",
(long) alignment);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020141,
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, 0x00020140,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Drive is busy on attempt to write random access",0,0);
return 0;
}
if(d->drive_role != 1) {
fd = burn_stdio_open_write(d, byte_address, 2048, 0);
if (fd == -1)
return 0;
}
d->busy = BURN_DRIVE_WRITING_SYNC;
d->buffer = &buf;
start = byte_address / 2048;
upto = start + data_count / 2048;
rpt = data;
for (; start < upto; start += 16) {
chunksize = upto - start;
if (chunksize > 16)
chunksize = 16;
d->buffer->bytes = chunksize * 2048;
memcpy(d->buffer->data, rpt, d->buffer->bytes);
rpt += d->buffer->bytes;
d->buffer->sectors = chunksize;
d->nwa = start;
if(d->drive_role == 1) {
err = d->write(d, d->nwa, d->buffer);
} else {
ret = burn_stdio_write(fd, (char *) d->buffer->data,
d->buffer->bytes, d, 0);
err = 0;
if (ret <= 0)
err = BE_CANCELLED;
}
if (err == BE_CANCELLED) {
d->busy = BURN_DRIVE_IDLE;
if(fd >= 0)
close(fd);
return (-(start * 2048 - byte_address));
}
}
if(d->drive_role == 1)
d->needs_sync_cache = 1;
if(flag & 1) {
if(d->drive_role == 1)
d->sync_cache(d);
else
burn_stdio_sync_cache(fd, d, 0);
d->needs_sync_cache = 0;
}
if(fd >= 0)
close(fd);
d->buffer = NULL;
d->busy = BURN_DRIVE_IDLE;
return 1;
}

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,15 +1,15 @@
/* test/libburner.c , API illustration of burning data or audio tracks to CD */
/* Copyright (C) 2005 - 2006 Thomas Schmitt <scdbackup@gmx.net> */
/* Provided under GPL, see also "License and copyright aspects" at file end */
/* Copyright (C) 2005 - 2007 Thomas Schmitt <scdbackup@gmx.net> */
/* Provided under GPLv2,see also "License and copyright aspects" at file end */
/** Overview
libburner is a minimal demo application for the library libburn as provided
on http://libburnia.pykix.org . It can list the available devices, can
on http://libburnia-project.org . It can list the available devices, can
blank a CD-RW or DVD-RW, can format a DVD-RW, can burn to CD-R, CD-RW, DVD-R,
DVD+R, DVD+RW, DVD-RAM or DVD-RW. Not supported yet: double layer media.
DVD+R, DVD+R/DL, DVD+RW, DVD-RAM or DVD-RW. Not supported yet: DVD-R/DL, BD.
It's main purpose, nevertheless, is to show you how to use libburn and also
to serve the libburnia team as reference application. libburner.c does indeed
@ -29,7 +29,7 @@
libburner_blank_disc()
or you can format a DVD-RW to profile "Restricted Overwrite" (needed once)
libburner_format_row()
With the aquired drive you can burn to CD-R, CD-RW, DVD+RW, DVD-RAM, DVD-RW
With the aquired drive you can burn to CD or DVD
libburner_payload()
When everything is done, main() releases the drive and shuts down libburn:
burn_drive_release();
@ -123,21 +123,28 @@ int libburner_aquire_by_adr(char *drive_adr)
int ret;
char libburn_drive_adr[BURN_DRIVE_ADR_LEN];
/* Some not-so-harmless drive addresses get blocked in this demo */
if (strncmp(drive_adr, "stdio:/dev/fd/", 14) == 0 ||
strcmp(drive_adr, "stdio:-") == 0) {
fprintf(stderr, "Will not work with pseudo-drive '%s'\n",
drive_adr);
return 0;
}
/* This tries to resolve links or alternative device files */
ret = burn_drive_convert_fs_adr(drive_adr, libburn_drive_adr);
if (ret<=0) {
fprintf(stderr,"Address does not lead to a CD burner: '%s'\n",
fprintf(stderr, "Address does not lead to a CD burner: '%s'\n",
drive_adr);
return ret;
return 0;
}
printf("Aquiring drive '%s' ...\n",libburn_drive_adr);
ret = burn_drive_scan_and_grab(&drive_list,libburn_drive_adr,1);
fprintf(stderr,"Aquiring drive '%s' ...\n", libburn_drive_adr);
ret = burn_drive_scan_and_grab(&drive_list, libburn_drive_adr, 1);
if (ret <= 0) {
fprintf(stderr,"FAILURE with persistent drive address '%s'\n",
libburn_drive_adr);
} else {
printf("Done\n");
fprintf(stderr,"Done\n");
drive_is_grabbed = 1;
}
return ret;
@ -163,7 +170,7 @@ int libburner_aquire_by_driveno(int *driveno)
printf("Beginning to scan for devices ...\n");
while (!burn_drive_scan(&drive_list, &drive_count))
usleep(1002);
usleep(100002);
if (drive_count <= 0 && *driveno >= 0) {
printf("FAILED (no drives found)\n");
return 0;
@ -352,6 +359,10 @@ int libburner_format_row(struct burn_drive *drive)
To make sure a data image is fully readable on any Linux machine, this
function adds 300 kiB of padding to the (usualy single) track.
Audio tracks get padded to complete their last sector.
A fifo of 4 MB is installed between each track and its data source.
Each of the 4 MB buffers gets allocated automatically as soon as a track
begins to be processed and it gets freed as soon as the track is done.
The fifos do not wait for buffer fill but writing starts immediately.
In case of external signals expect abort handling of an ongoing burn to
last up to a minute. Wait the normal burning timespan before any kill -9.
@ -363,7 +374,7 @@ int libburner_payload(struct burn_drive *drive,
char source_adr[][4096], int source_adr_count,
int multi, int simulate_burn, int all_tracks_type)
{
struct burn_source *data_src;
struct burn_source *data_src, *fifo_src[99];
struct burn_disc *target_disc;
struct burn_session *session;
struct burn_write_opts *burn_options;
@ -372,6 +383,7 @@ int libburner_payload(struct burn_drive *drive,
struct burn_progress progress;
time_t start_time;
int last_sector = 0, padding = 0, trackno, unpredicted_size = 0, fd;
int fifo_chunksize = 2352, fifo_chunks = 1783; /* ~ 4 MB fifo */
off_t fixed_size;
char *adr, reasons[BURN_REASONS_LEN];
struct stat stbuf;
@ -380,6 +392,8 @@ int libburner_payload(struct burn_drive *drive,
all_tracks_type = BURN_MODE1;
/* a padding of 300 kiB helps to avoid the read-ahead bug */
padding = 300*1024;
fifo_chunksize = 2048;
fifo_chunks = 2048; /* 4 MB fifo */
}
target_disc = burn_disc_create();
@ -390,6 +404,7 @@ int libburner_payload(struct burn_drive *drive,
tracklist[trackno] = track = burn_track_create();
burn_track_define_data(track, 0, padding, 1, all_tracks_type);
/* Open file descriptor to source of track data */
adr = source_adr[trackno];
fixed_size = 0;
if (adr[0] == '-' && adr[1] == 0) {
@ -403,6 +418,8 @@ int libburner_payload(struct burn_drive *drive,
}
if (fixed_size==0)
unpredicted_size = 1;
/* Convert this filedescriptor into a burn_source object */
data_src = NULL;
if (fd>=0)
data_src = burn_fd_source_new(fd, -1, fixed_size);
@ -414,14 +431,29 @@ int libburner_payload(struct burn_drive *drive,
strerror(errno));
return 0;
}
if (burn_track_set_source(track, data_src) != BURN_SOURCE_OK) {
printf("FATAL: Cannot attach source object to track object\n");
/* Install a fifo object on top of that data source object */
fifo_src[trackno] = burn_fifo_source_new(data_src,
fifo_chunksize, fifo_chunks, 0);
if (fifo_src[trackno] == NULL) {
fprintf(stderr,
"FATAL: Could not create fifo object of 4 MB\n");
return 0;
}
/* Use the fifo object as data source for the track */
if (burn_track_set_source(track, fifo_src[trackno])
!= BURN_SOURCE_OK) {
fprintf(stderr,
"FATAL: Cannot attach source object to track object\n");
return 0;
}
burn_session_add_track(session, track, BURN_POS_END);
printf("Track %d : source is '%s'\n", trackno+1, adr);
/* Give up local reference to the data burn_source object */
burn_source_free(data_src);
} /* trackno loop end */
/* Evaluate drive and media */
@ -461,25 +493,44 @@ int libburner_payload(struct burn_drive *drive,
burn_write_opts_free(burn_options);
while (burn_drive_get_status(drive, NULL) == BURN_DRIVE_SPAWNING)
usleep(1002);
usleep(100002);
while (burn_drive_get_status(drive, &progress) != BURN_DRIVE_IDLE) {
if( progress.sectors <= 0 || progress.sector == last_sector)
if (progress.sectors <= 0 ||
(progress.sector >= progress.sectors - 1 &&
!unpredicted_size) ||
(unpredicted_size && progress.sector == last_sector))
printf(
"Thank you for being patient since %d seconds.\n",
"Thank you for being patient since %d seconds.",
(int) (time(0) - start_time));
else if(unpredicted_size)
printf("Track %d : sector %d\n", progress.track+1,
printf("Track %d : sector %d", progress.track+1,
progress.sector);
else
printf("Track %d : sector %d of %d\n",progress.track+1,
printf("Track %d : sector %d of %d",progress.track+1,
progress.sector, progress.sectors);
last_sector = progress.sector;
if (progress.track >= 0 && progress.track < source_adr_count) {
int size, free_bytes, ret;
char *status_text;
ret = burn_fifo_inquire_status(
fifo_src[progress.track], &size, &free_bytes,
&status_text);
if (ret >= 0 )
printf(" [fifo %s, %2d%% fill]", status_text,
(int) (100.0 - 100.0 *
((double) free_bytes) /
(double) size));
}
printf("\n");
sleep(1);
}
printf("\n");
for (trackno = 0 ; trackno < source_adr_count; trackno++)
for (trackno = 0 ; trackno < source_adr_count; trackno++) {
burn_source_free(fifo_src[trackno]);
burn_track_free(tracklist[trackno]);
}
burn_session_free(session);
burn_disc_free(target_disc);
if (multi && current_profile != 0x1a && current_profile != 0x13 &&
@ -620,7 +671,7 @@ int main(int argc, char **argv)
if (ret)
exit(ret);
printf("Initializing libburnia.pykix.org ...\n");
printf("Initializing libburnia-project.org ...\n");
if (burn_initialize())
printf("Done\n");
else {

View File

@ -1,11 +1,12 @@
/* test/telltoc.c , API illustration of obtaining media status info */
/* Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net> Provided under GPL */
/* Copyright (C) 2006 - 2007 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 */
/** Overview
telltoc is a minimal demo application for the library libburn as provided
on http://libburnia.pykix.org . It can list the available devices, can
on http://libburnia-project.org . It can list the available devices, can
display some drive properties, the type of media, eventual table of content
and multisession info for mkisofs option -C .
It's main purpose, nevertheless, is to show you how to use libburn and also
@ -24,6 +25,8 @@
telltoc_media() prints some information about the media in a drive
telltoc_toc() prints a table of content (if there is content)
telltoc_msinfo() prints parameters for mkisofs option -C
telltoc_read_and_print() reads from data CD or from DVD and prints 7-bit
to stdout (encodings 0,2) or 8-bit to file (encoding 1)
When everything is done, main() releases the drive and shuts down libburn:
burn_drive_release();
burn_finish()
@ -72,6 +75,11 @@ int telltoc_aquire_by_adr(char *drive_adr);
int telltoc_aquire_by_driveno(int *drive_no, int silent);
/* A message from --toc to --read_and_print (CD tracksize is a bit tricky) */
static int last_track_start = 0, last_track_size = -1;
static int media_is_cd_profile = 0;
/* ------------------------------- API gestures ---------------------------- */
/** You need to aquire a drive before burning. The API offers this as one
@ -100,22 +108,33 @@ int telltoc_aquire_drive(char *drive_adr, int *driveno, int silent_drive)
/** If the persistent drive address is known, then this approach is much
more un-obtrusive to the systemwide livestock of drives. Only the
given drive device will be opened during this procedure.
Special drive addresses stdio:<path> direct output to a hard disk file
which will behave much like a DVD-RAM.
*/
int telltoc_aquire_by_adr(char *drive_adr)
{
int ret;
char libburn_drive_adr[BURN_DRIVE_ADR_LEN];
/* <<< ts A70907 FOR TESTING ONLY !
struct burn_drive_info *test_drive_list;
*/
/* This tries to resolve links or alternative device files */
ret = burn_drive_convert_fs_adr(drive_adr, libburn_drive_adr);
if (ret<=0) {
fprintf(stderr,"Address does not lead to a CD burner: '%s'\n",
fprintf(stderr, "Address does not lead to a CD burner: '%s'\n",
drive_adr);
return ret;
return 0;
}
fprintf(stderr,"Aquiring drive '%s' ...\n",libburn_drive_adr);
ret = burn_drive_scan_and_grab(&drive_list,libburn_drive_adr,1);
/* <<< ts A70907 FOR TESTING ONLY !
ret = burn_drive_scan_and_grab(&test_drive_list, "/dev/sg2", 1);
*/
fprintf(stderr,"Aquiring drive '%s' ...\n", libburn_drive_adr);
ret = burn_drive_scan_and_grab(&drive_list, libburn_drive_adr, 1);
if (ret <= 0) {
fprintf(stderr,"FAILURE with persistent drive address '%s'\n",
libburn_drive_adr);
@ -123,6 +142,11 @@ int telltoc_aquire_by_adr(char *drive_adr)
fprintf(stderr,"Done\n");
drive_is_grabbed = 1;
}
/* <<< ts A70907 FOR TESTING ONLY !
burn_drive_info_free(test_drive_list);
*/
return ret;
}
@ -147,7 +171,7 @@ int telltoc_aquire_by_driveno(int *driveno, int silent_drive)
fprintf(stderr, "Beginning to scan for devices ...\n");
while (!burn_drive_scan(&drive_list, &drive_count))
usleep(1002);
usleep(100002);
if (drive_count <= 0 && *driveno >= 0) {
fprintf(stderr, "FAILED (no drives found)\n");
return 0;
@ -234,7 +258,7 @@ int telltoc_media(struct burn_drive *drive)
printf("Media current: ");
ret = burn_disc_get_profile(drive, &profile_no, profile_name);
if (profile_no > 0 && ret >0) {
if (profile_no > 0 && ret > 0) {
if (profile_name[0])
printf("%s\n", profile_name);
else
@ -443,8 +467,9 @@ int telltoc_formatlist(struct burn_drive *drive)
int telltoc_toc(struct burn_drive *drive)
{
int num_sessions = 0 , num_tracks = 0 , lba = 0, pmin, psec, pframe;
int track_count = 0;
int track_count = 0, pno;
int session_no, track_no;
char profile_name[80];
struct burn_disc *disc= NULL;
struct burn_session **sessions;
struct burn_track **tracks;
@ -479,6 +504,7 @@ int telltoc_toc(struct burn_drive *drive)
track_count,
((toc_entry.control&7)<4?"audio":"data "),
lba, pmin, psec, pframe);
last_track_start = lba;
}
burn_session_get_leadout_entry(sessions[session_no],
&toc_entry);
@ -494,6 +520,11 @@ int telltoc_toc(struct burn_drive *drive)
printf("Media content: session %2d ", session_no+1);
printf("leadout lba: %9d %4.2d:%2.2d:%2.2d\n",
lba, pmin, psec, pframe);
last_track_size = lba - last_track_start;
if (burn_disc_get_profile(drive, &pno, profile_name) > 0)
if (pno == 0x09 || pno == 0x0a)
media_is_cd_profile = 1;
}
if (disc!=NULL)
burn_disc_free(disc);
@ -558,6 +589,125 @@ ex:;
}
/**
@param encoding determins how to format output on stdout:
0 = default , 1 = raw 8 bit (dangerous for tty) , 2 = hex
*/
int telltoc_read_and_print(struct burn_drive *drive,
int start_sector, int sector_count, char *raw_file, int encoding)
{
int j, i, request = 16, done, lbas = 0, final_cd_try = -1, todo;
int ret = 0;
char buf[16 * 2048], line[81];
off_t data_count, total_count= 0, last_reported_count= 0;
struct stat stbuf;
FILE *raw_fp = NULL;
if (start_sector == -1)
start_sector = last_track_start;
if (sector_count == -1) {
sector_count = last_track_start + last_track_size
- start_sector;
if (media_is_cd_profile) /* In case it is a TAO track */
final_cd_try = 0; /* allow it (-1 is denial) */
}
if (start_sector < 0)
start_sector = 0;
if (sector_count <= 0)
sector_count = 2147483632;
if (sector_count <= 0)
return -1;
if (encoding == 1) {
if (stat(raw_file,&stbuf) != -1) {
if (!(S_ISCHR(stbuf.st_mode) || S_ISFIFO(stbuf.st_mode)
|| (stbuf.st_mode & S_IFMT) == S_IFSOCK )) {
fprintf(stderr,
"SORRY: target file '%s' already existing\n",
raw_file);
return 1;
}
}
raw_fp = fopen(raw_file,"w");
if (raw_fp == NULL) {
fprintf(stderr,"SORRY: cannot open target file '%s' (%s)\n", raw_file, strerror(errno));
return 1;
}
printf(
"Data : start=%ds , count=%ds , read=0s , encoding=%d:'%s'\n",
start_sector, sector_count, encoding, raw_file);
} else
printf(
"Data : start=%ds , count=%ds , read=0 , encoding=%d\n",
start_sector, sector_count, encoding);
todo = sector_count - 2*(final_cd_try > -1);
for (done = 0; done < todo && final_cd_try != 1; done += request) {
if (todo - done > 16)
request = 16;
else
request = todo - done;
ret = burn_read_data(drive,
((off_t) start_sector + done) * (off_t) 2048,
buf, (off_t) (request * 2048), &data_count, 1);
print_result:;
total_count += data_count;
if (encoding == 1) {
if (data_count > 0)
fwrite(buf, data_count, 1, raw_fp);
} else for (i = 0; i < data_count; i += 16) {
if (encoding == 0) {
sprintf(line, "%8ds + %4d : ",
start_sector + done + i / 2048,
i % 2048);
lbas = strlen(line);
}
for (j = 0; j < 16 && i + j < data_count; j++) {
if (buf[i + j] >= ' ' && buf[i + j] <= 126 &&
encoding != 2)
sprintf(line + lbas + 3 * j, " %c ",
(int) buf[i + j]);
else
sprintf(line + lbas + 3 * j, "%2.2X ",
(unsigned char) buf[i + j]);
}
line[lbas + 3 * (j - 1) + 2] = 0;
printf("%s\n",line);
}
if (encoding == 1 &&
total_count - last_reported_count >= 1000 * 2048) {
fprintf(stderr,
"\rReading data : start=%ds , count=%ds , read=%ds ",
start_sector, sector_count,
(int) (total_count / (off_t) 2048));
last_reported_count = total_count;
}
if (ret <= 0) {
fprintf(stderr, "SORRY : Reading failed.\n");
break;
}
}
if (ret > 0 && media_is_cd_profile && final_cd_try == 0) {
/* In a SAO track the last 2 frames should be data too */
final_cd_try = 1;
burn_read_data(drive,
((off_t) start_sector + todo) * (off_t) 2048,
buf, (off_t) (2 * 2048), &data_count, 2);
if (data_count < 2 * 2048)
fprintf(stderr, "\rNOTE : Last two frames of CD track unreadable. This is normal if TAO track.\n");
if (data_count > 0)
goto print_result;
}
if (last_reported_count > 0)
fprintf(stderr,
"\r \r");
printf("End Of Data : start=%ds , count=%ds , read=%ds\n",
start_sector, sector_count,(int) (total_count / (off_t) 2048));
return ret;
}
/** The setup parameters of telltoc */
static char drive_adr[BURN_DRIVE_ADR_LEN] = {""};
static int driveno = 0;
@ -566,6 +716,8 @@ static int do_toc = 0;
static int do_msinfo = 0;
static int print_help = 0;
static int do_capacities = 0;
static int read_start = -2, read_count = -2, print_encoding = 0;
static char print_raw_file[4096] = {""};
/** Converts command line arguments into above setup parameters.
@ -608,6 +760,26 @@ int telltoc_setup(int argc, char **argv)
} else if (!strcmp(argv[i], "--toc")) {
do_toc = 1;
} else if (!strcmp(argv[i], "--read_and_print")) {
i+= 3;
if (i >= argc) {
fprintf(stderr,"--read_and_print requires three arguments: start count encoding(try 0, not 1)\n");
return 1;
}
sscanf(argv[i-2], "%d", &read_start);
sscanf(argv[i-1], "%d", &read_count);
print_encoding = 0;
if(strncmp(argv[i], "raw:", 4) == 0 || strcmp(argv[i],"1:") == 0) {
print_encoding = 1;
strcpy(print_raw_file, strchr(argv[i], ':') + 1);
if (strcmp(print_raw_file, "-") == 0) {
fprintf(stderr,
"--read_and_print does not write to \"-\" as stdout.\n");
return 1;
}
} else if(strcmp(argv[i], "hex") == 0 || strcmp(argv[i], "2") == 0)
print_encoding = 2;
} else if (!strcmp(argv[i], "--help")) {
print_help = 1;
@ -622,6 +794,7 @@ int telltoc_setup(int argc, char **argv)
printf("Usage: %s\n", argv[0]);
printf(" [--drive <address>|<driveno>|\"-\"]\n");
printf(" [--media] [--capacities] [--toc] [--msinfo]\n");
printf(" [--read_and_print <start> <count> \"0\"|\"hex\"|\"raw\":<path>]\n");
printf("Examples\n");
printf("A bus scan (needs rw-permissions to see a drive):\n");
printf(" %s --drive -\n",argv[0]);
@ -635,6 +808,12 @@ int telltoc_setup(int argc, char **argv)
printf(" mkisofs ... -C \"$msinfo\" ...\n");
printf("Obtain what is available about drive 0 and its media\n");
printf(" %s --drive 0\n",argv[0]);
printf("View blocks 16 to 19 of data CD or DVD in human readable form\n");
printf(" %s --drive /dev/sr1 --read_and_print 16 4 0 | less\n",
argv[0]);
printf("Copy last data track from CD to file /tmp/data\n");
printf(" %s --drive /dev/sr1 --toc --read_and_print -1 -1 raw:/tmp/data\n",
argv[0]);
}
return 0;
}
@ -656,14 +835,14 @@ int main(int argc, char **argv)
msinfo_alone = 1;
}
/* Default option is to do everything if possible */
if (do_media==0 && do_msinfo==0 && do_capacities==0 && do_toc==0
&& driveno!=-1) {
if (do_media==0 && do_msinfo==0 && do_capacities==0 && do_toc==0 &&
(read_start < 0 || read_count <= 0) && driveno!=-1) {
if(print_help)
exit(0);
full_default = do_media = do_msinfo = do_capacities= do_toc = 1;
full_default = do_media = do_msinfo = do_capacities= do_toc= 1;
}
fprintf(stderr, "Initializing libburnia.pykix.org ...\n");
fprintf(stderr, "Initializing libburnia-project.org ...\n");
if (burn_initialize())
fprintf(stderr, "Done\n");
else {
@ -671,8 +850,11 @@ int main(int argc, char **argv)
exit(33);
}
/* Print messages of severity SORRY or more directly to stderr */
burn_msgs_set_severities("NEVER", "SORRY", "telltoc : ");
/* Print messages of severity WARNING or more directly to stderr */
burn_msgs_set_severities("NEVER", "WARNING", "telltoc : ");
/* Activate the default signal handler */
burn_set_signal_handling("telltoc : ", NULL, 0);
/** Note: driveno might change its value in this call */
ret = telltoc_aquire_drive(drive_adr, &driveno, !full_default);
@ -709,6 +891,13 @@ int main(int argc, char **argv)
if (ret<=0)
{ret = 38; goto release_drive; }
}
if (read_start >= -1 && (read_count > 0 || read_count == -1)) {
ret = telltoc_read_and_print(drive_list[driveno].drive,
read_start, read_count, print_raw_file,
print_encoding);
if (ret<=0)
{ret = 40; goto release_drive; }
}
ret = 0;
if (toc_failed)