Compare commits
1246 Commits
CdrskinZer
...
1.1.0.pl01
Author | SHA1 | Date | |
---|---|---|---|
3d8f4491c4 | |||
8f36e9b8d5 | |||
806829e215 | |||
88fdf1f89a | |||
91adddd7b0 | |||
3cf354654e | |||
0698621318 | |||
9727bb8fc4 | |||
4abf2b75b1 | |||
f93babeea6 | |||
54723c9ee3 | |||
75f121d26e | |||
9ee4f65141 | |||
8d057e4ee4 | |||
47af302776 | |||
c96745af15 | |||
99af1501fc | |||
aeff7957f2 | |||
5f743b8030 | |||
27997067c9 | |||
cf8e46ec32 | |||
bad7a81d0d | |||
5e8e73d994 | |||
5ba8c03a98 | |||
096ed00f2e | |||
b4aeba18f7 | |||
0352486f97 | |||
edd131b1b9 | |||
30f3f70dfd | |||
806b9602e6 | |||
f116eeec64 | |||
7e50165d5c | |||
46357869fc | |||
f85cb8269f | |||
8fffc74a5b | |||
8fd81d4ec4 | |||
0c76daf2a9 | |||
86656a9d52 | |||
95e511b984 | |||
7af151169d | |||
7a9a7dfdd2 | |||
0ac6a64f12 | |||
8bd288e10c | |||
28078d059a | |||
ac665916a6 | |||
e9637067f8 | |||
a058e24375 | |||
f895077c3c | |||
73423b8819 | |||
5e9c7bac3f | |||
e32bd99801 | |||
e86a7f9880 | |||
9c9b82ae61 | |||
d5cc482015 | |||
1f14074d59 | |||
d0c6889603 | |||
a088a85374 | |||
a3ac6c63aa | |||
af41742516 | |||
998fcdbefa | |||
ed811f45e6 | |||
240e6abff4 | |||
402f4c0b04 | |||
1b166f484d | |||
b945974dc7 | |||
cf214650c6 | |||
69ec9334d1 | |||
238fde4ef1 | |||
69e95016fb | |||
a8e54b86d7 | |||
9f5e967bdf | |||
fcaf3e9d9a | |||
b59429c568 | |||
1f72fe107d | |||
043d9a82d8 | |||
952c9b0432 | |||
4f5075d7a9 | |||
2b07bd0632 | |||
0a714850d7 | |||
3caf176aeb | |||
43f7e7d063 | |||
447a68d691 | |||
0a3b34d9c1 | |||
0b25a4d258 | |||
3b5aeb0f81 | |||
5ec4a7419e | |||
bf7e4c8027 | |||
682078575f | |||
43f3d4b70f | |||
523b59984b | |||
dcf79a188a | |||
84d6cac5c1 | |||
261f05eb45 | |||
9334b3190d | |||
9b0772fe9c | |||
20c0ae24a8 | |||
0f622def33 | |||
707d6153f7 | |||
28ae78b4f1 | |||
7ceb67f0b0 | |||
e18bfe50c1 | |||
4083001548 | |||
45353dee67 | |||
f14b66a09b | |||
38c029d5e3 | |||
287b59cfd3 | |||
c49995b11a | |||
f2436351ef | |||
71844bf8b9 | |||
59e0824370 | |||
b7034abcbb | |||
df390ae7d3 | |||
c1f4063193 | |||
4cc524097b | |||
fb159b8dbd | |||
c693798571 | |||
34847fff80 | |||
54651df146 | |||
d4e4607a84 | |||
98b2e06c21 | |||
d5ecb382aa | |||
cdcda19384 | |||
b96aeece99 | |||
7bbf99384e | |||
9f61db5378 | |||
2a48b34bcd | |||
15266fb310 | |||
e2bdd521d8 | |||
7a3b871c4e | |||
713ec46f23 | |||
85eb091025 | |||
c866b6bc35 | |||
0250a2831d | |||
4c47b81a9c | |||
bb88ba5861 | |||
b30a2af7c7 | |||
b10cfb3d22 | |||
a2df41713d | |||
86ce32d170 | |||
7ba30596ce | |||
2f8ad976ea | |||
d0d37af096 | |||
81768cd4b0 | |||
e9828cddd0 | |||
7f0358892a | |||
bc40ce2876 | |||
6674667b7f | |||
cc4d72bf8b | |||
1eee6ab8a0 | |||
736d8b9019 | |||
8345eb8a71 | |||
cc7548f1c7 | |||
edca339338 | |||
9323cceff1 | |||
8b1b3f08c6 | |||
e332f4a438 | |||
960fe6d188 | |||
92c5f6f998 | |||
2069ffa863 | |||
e787d328c7 | |||
fafc190fd4 | |||
e6029ae238 | |||
6e17c59f6b | |||
0e777ec688 | |||
8dcdb5a87f | |||
4f372c00bc | |||
9f6d80d87d | |||
b33df8fbd5 | |||
b4bb522053 | |||
3289ffd1e6 | |||
196ef37108 | |||
cdad7fcd80 | |||
ed6e2df81b | |||
ae667ca2e8 | |||
873e3f5d78 | |||
72f9ff8b8c | |||
eb95f7fc16 | |||
3519b42c14 | |||
b4e5afd317 | |||
7446ed7daa | |||
2d40b098e5 | |||
ac64aef090 | |||
74a68adc6e | |||
937bc87bfc | |||
de482489c1 | |||
295fa1d526 | |||
99bba3e98e | |||
bd3016e085 | |||
dd74364ebb | |||
255e5362f9 | |||
471a0d0058 | |||
f5b556db47 | |||
c12bbff7d1 | |||
6db992e646 | |||
bd017a108e | |||
3a76f9245f | |||
580ca08cc5 | |||
a6bd4c24db | |||
54005cb60e | |||
15fbe0a7ea | |||
da1d260753 | |||
95865ee34d | |||
eb8b8faa3b | |||
39fd8b922d | |||
7ead54c8b9 | |||
2a85fc7d91 | |||
1e42a76415 | |||
734759190a | |||
16ffa10831 | |||
cdfc357064 | |||
df612390d3 | |||
77971f3680 | |||
5c75d583d7 | |||
2ff03841d7 | |||
a88745c82e | |||
96167b3d8e | |||
1ca38962d4 | |||
80bcabfd57 | |||
d9239aeafc | |||
758a197d06 | |||
ed972271ec | |||
0544ac8cd3 | |||
12a2be8d86 | |||
509db68d82 | |||
00ed59f34e | |||
2b8e8c2521 | |||
e3ff0bb0f6 | |||
8efb24ca6d | |||
d53c5db98e | |||
0320b7bf2a | |||
cee271f9cb | |||
c2a3e3677d | |||
fc3445215b | |||
4ce8bd45cf | |||
08169d63bc | |||
e13b6369ba | |||
d3988dd74b | |||
ef42052900 | |||
240afa7c3a | |||
5b72e5d06e | |||
4aa08e32ff | |||
eb34561262 | |||
dd85e37ac8 | |||
e566340261 | |||
7e86db207c | |||
a30ecd1abb | |||
45b28b6c31 | |||
afedcdd72b | |||
b8a98e0728 | |||
b238ad5a51 | |||
28f4454a9d | |||
cb8c23ed5a | |||
54bb1ab395 | |||
872068ba7c | |||
2bd800ed14 | |||
da0b3b3939 | |||
93aa6ccc6f | |||
d6edfc9961 | |||
2945ab61d7 | |||
d35f7d0de1 | |||
e335aa26b4 | |||
496d794bcd | |||
c88a428d5e | |||
dc8ecdd77e | |||
259d1cd2b7 | |||
7fddf9ffc5 | |||
6109a7bc08 | |||
9b28a9b272 | |||
f39ff2c2f6 | |||
c8e0472637 | |||
acb2f3b173 | |||
504677de4f | |||
ae8f65e956 | |||
c2c10e263e | |||
43761c55ef | |||
b28165f10b | |||
25489521bb | |||
79a33ca2ac | |||
738b83ac03 | |||
677b007100 | |||
0fc685fc85 | |||
ca2cae9b0a | |||
055876d6b7 | |||
9160b1dcbb | |||
0f37170759 | |||
ce3d4dbed3 | |||
f9acd4ee3d | |||
d118b82a13 | |||
76a4c0ac44 | |||
83f80364c5 | |||
9064b56c56 | |||
405e6b020e | |||
ffe80264c7 | |||
d158e7f456 | |||
4384b0c006 | |||
e78353b7dd | |||
3c2ad1be42 | |||
937a226543 | |||
cca24711b8 | |||
e646686145 | |||
f3070d2e71 | |||
e0c501a59a | |||
39a7d18266 | |||
de8ecab9b4 | |||
e9a6b9c36d | |||
e65ccb2b5e | |||
96a5a2a28a | |||
ca97df9798 | |||
22905f7349 | |||
a318da9463 | |||
3c69b684a8 | |||
4457061656 | |||
758f5a5c1e | |||
c8c4da8e8e | |||
4fdebcae9f | |||
82ee4c8788 | |||
ad4a286736 | |||
9017f0716f | |||
7973546a4c | |||
2e6f83b3b3 | |||
fdd190b65c | |||
97ac17512f | |||
28a1b4dcba | |||
b724ab2130 | |||
567beb1d9f | |||
eb62395e41 | |||
1d6c97c79f | |||
5e4c1cf967 | |||
719096b0a7 | |||
75dca6c6e9 | |||
1ef3a24885 | |||
790b4f31ee | |||
9362a0240b | |||
82e884c432 | |||
f6d6dcfad0 | |||
970ae46cfa | |||
693784cbf5 | |||
3a98bc52f9 | |||
6038928fe4 | |||
2e547b0bba | |||
e968e81409 | |||
557299d350 | |||
6642342274 | |||
40b3380d4d | |||
3b018684c7 | |||
96beb44455 | |||
9805ce7534 | |||
407471898c | |||
cf9a2031a4 | |||
d9fc6cc275 | |||
78713d8912 | |||
169963eced | |||
22c187cd61 | |||
b900831914 | |||
654d71ef07 | |||
0571f4dc2e | |||
ff23614200 | |||
c59300b27a | |||
635996a327 | |||
93287896a6 | |||
4da88193fa | |||
3091eeb9c9 | |||
19a668a48e | |||
6ceabaff32 | |||
b65b852c15 | |||
1ccedd5572 | |||
473e205c9e | |||
2522bebfbd | |||
8276611468 | |||
38994b62c0 | |||
474c4cddd7 | |||
b0b4bc57f8 | |||
b97fa7a451 | |||
8aca8e9921 | |||
15b31b121a | |||
e5632de786 | |||
91e3a2f3f7 | |||
0ffc4bd19b | |||
9cb4e4281e | |||
f87747802a | |||
4626304e39 | |||
d19abc1940 | |||
5ef7b4b445 | |||
033107b436 | |||
635405da8f | |||
aafa543391 | |||
8594cd96bc | |||
b07c83ed86 | |||
d74b1a2008 | |||
8c56ca131f | |||
53e4483460 | |||
591c385489 | |||
b0f1f67495 | |||
6139fb32dd | |||
01ed4729bd | |||
350ac05bfd | |||
5f55a436e8 | |||
3baaa886be | |||
d4147e72f0 | |||
116798e081 | |||
7cc43c44e9 | |||
de0b3dd469 | |||
596d5bc5b0 | |||
867093d7d4 | |||
47dd4d8c09 | |||
01a825310e | |||
96043eddf5 | |||
5a65d6fa07 | |||
aca01b88f3 | |||
6d667880e5 | |||
1a667c86bc | |||
7c64d4bc13 | |||
6fea3d0a9b | |||
687bde257c | |||
1de41908a8 | |||
8af33586e8 | |||
3ea5106d68 | |||
0ca643d0a4 | |||
d50c90b7be | |||
1b5ab0834e | |||
147cb430d1 | |||
1cbe3afdcc | |||
817edbaeea | |||
6552c8267c | |||
82fcf62309 | |||
c1572c271f | |||
83ed108298 | |||
0d669b4369 | |||
22554efe4f | |||
eb7e20a02c | |||
a5e2729604 | |||
d52ea49eb6 | |||
96e1cc451c | |||
bfba58b0fa | |||
175061615e | |||
717ad0f412 | |||
f3ea35b9b8 | |||
bb9ef6b988 | |||
aa606552eb | |||
9d99e7874a | |||
d1483a15da | |||
ed60d9a644 | |||
bd5d8e8991 | |||
bf64271c67 | |||
b0c8bbd48d | |||
2fb19dd08e | |||
2ce3199241 | |||
6fe53827da | |||
6053f3a6e3 | |||
de274ddaff | |||
92b0e145d5 | |||
4a5083739d | |||
7a8040fe9f | |||
57df15054f | |||
a57cf121d8 | |||
935239b4f9 | |||
e50cc04374 | |||
89c12404d0 | |||
78642d08ae | |||
c2c2499862 | |||
32252122b8 | |||
63a48571af | |||
006fb98aee | |||
afded80e10 | |||
fb3d2de5df | |||
c640c7954b | |||
bc30c4201a | |||
50b587a22c | |||
cd99716ab5 | |||
13bdbd3555 | |||
711c055730 | |||
f64ed23a98 | |||
730c1555ab | |||
acd7dbc5c6 | |||
6dc9ecbcad | |||
5a99f9c4d8 | |||
ea17318e18 | |||
98d742a4ef | |||
332a92ac78 | |||
6c50416d3c | |||
91d678a503 | |||
76e85e600c | |||
9d48bb6892 | |||
38f0399fff | |||
39198ff8cb | |||
67ca4a251a | |||
b1c6953b61 | |||
eb95d89272 | |||
548051e53f | |||
a72b38c116 | |||
a67aa2ccee | |||
2fb5ea8def | |||
55061cb7cf | |||
4b3ec06cc4 | |||
ad6bd91b21 | |||
0e2aaa2d59 | |||
4244a3c141 | |||
e4d30e4762 | |||
2856e9c984 | |||
6660ef7ece | |||
37092086d9 | |||
35d1394262 | |||
4dec38984d | |||
be0626ae9e | |||
a54113267e | |||
2d9d250471 | |||
ff7520f2f5 | |||
d0d90fc902 | |||
1d41767348 | |||
12b0fbf17c | |||
44368aef6c | |||
43b6ad6008 | |||
f006ee5436 | |||
5e4da147a5 | |||
103b301b09 | |||
0386feabfe | |||
4e949d79fe | |||
422a97a2f2 | |||
a52ea438a5 | |||
62f41452bb | |||
015bc00a91 | |||
d6fde26824 | |||
1cfb29f032 | |||
65cf751a30 | |||
4683386de1 | |||
5d51869c3b | |||
fe8a6c6224 | |||
db5568c03b | |||
a07631c57b | |||
e522db6220 | |||
51ac900de6 | |||
cdea153443 | |||
0ce3f7c224 | |||
8de0a3dc6c | |||
e75e5e04b8 | |||
86d5bdfef8 | |||
c1298d82a6 | |||
5c6366ecbd | |||
616454c737 | |||
ea6957ef68 | |||
f9398c08e6 | |||
b4617c679c | |||
42bb74881a | |||
61671b41d7 | |||
1e74d7a04e | |||
c48244abfc | |||
13492efe4b | |||
bccb39efd8 | |||
6fc60be93c | |||
d69b856b6a | |||
b5e2d60c68 | |||
ff1ad50119 | |||
4cb6706307 | |||
6e74c8bc2e | |||
fdbed06f84 | |||
67e4282b82 | |||
bd8d4bb49f | |||
623edf9d9d | |||
d4fe8c75be | |||
9ebd020847 | |||
a93d18231a | |||
ec8b75217f | |||
99767afe1f | |||
024076ad54 | |||
c39e7d8ce4 | |||
95609061f1 | |||
d498003515 | |||
b1630a3b33 | |||
eddf4e6b13 | |||
654e25d40a | |||
69e1d4a51f | |||
305917fe86 | |||
b3b42ff649 | |||
63d1f5dcbf | |||
77a9a1fc92 | |||
beb1c1d2d1 | |||
e449654c7b | |||
d66a40bc0e | |||
bed900f3f4 | |||
922fc6c90b | |||
adac21d6ee | |||
d9e056c3ac | |||
32a6bd1f82 | |||
9f7be91aba | |||
fec4fd864f | |||
e48014caea | |||
82c6e92da0 | |||
206910da4e | |||
0a27b188a3 | |||
6705389f14 | |||
5c8d6865b5 | |||
2d6d2679a0 | |||
5432612965 | |||
9b1a57d84a | |||
e5ea580e3b | |||
981a1bf5e1 | |||
49925ad2ba | |||
fc5f2a4745 | |||
903a12c90b | |||
0f50c21888 | |||
f3739013fa | |||
bc5bb95dba | |||
cb68f7e0b7 | |||
63939c4f25 | |||
1280fdf221 | |||
3199bc21aa | |||
2d131a1741 | |||
cd84357589 | |||
e98a90cecf | |||
2a669879a4 | |||
e6885f7fac | |||
191db530c5 | |||
c3d9155340 | |||
3119ed2af3 | |||
5eb47cd3ed | |||
6864b1d621 | |||
5ad09b55ee | |||
f4fe30ec6c | |||
a63d9b11c4 | |||
ee7fcf7522 | |||
ed53a67a2b | |||
bc1944b970 | |||
e065ff1db7 | |||
e5f42759a0 | |||
f3966e5fee | |||
e2479d6088 | |||
291ef125b0 | |||
771e659a43 | |||
f71c2079ff | |||
01ec5f031d | |||
ce7678b8f4 | |||
769ea039a1 | |||
fc6163732e | |||
1efbf27fe3 | |||
214de7d7df | |||
97403bb20e | |||
5d93e04b28 | |||
3dda4b92b9 | |||
ec763a5ec9 | |||
06ec817caa | |||
ff9715aa78 | |||
7ec2972988 | |||
24d6db4b64 | |||
011ba599cd | |||
78c16e7590 | |||
c78403d8cf | |||
5e995c9cd0 | |||
83fe9f3621 | |||
9e4996a3b5 | |||
0721cf89d1 | |||
78dd75b1ff | |||
606c863a55 | |||
282e228a6b | |||
d8990e820e | |||
af3c8aaa5d | |||
1e78652ac9 | |||
a6f41f8beb | |||
9930c22d4a | |||
e71c12caf3 | |||
5e9b8b6341 | |||
5230cb0c1d | |||
85f24401a8 | |||
190ad329fd | |||
c8e9249e9d | |||
e43ec2b295 | |||
a80f8359fe | |||
129db7ee49 | |||
2748f396ae | |||
698866015e | |||
2b0ce8ec9a | |||
8fd2539a5c | |||
1077788276 | |||
361a110274 | |||
f379a2c91a | |||
7654785d43 | |||
15b9f786c8 | |||
635530b05e | |||
ab15717ce0 | |||
eb88f800d7 | |||
1786e8008f | |||
064ef80df9 | |||
488e970665 | |||
02ede28b9e | |||
e137f8fd20 | |||
854a806292 | |||
090861567d | |||
4b4f141fcc | |||
c70a78c477 | |||
542afd7b3b | |||
75dd141055 | |||
ffed552183 | |||
ea09a516bd | |||
ccad19e055 | |||
bdf862b429 | |||
bdff3ac16c | |||
2d3d255231 | |||
8bf8287c58 | |||
40cb77d953 | |||
df382b3f06 | |||
c8c349469d | |||
1f7a6575bc | |||
386149d5bf | |||
c62e63a8d9 | |||
1935d222ed | |||
b812af96f7 | |||
5a8910cdd8 | |||
0bbc34d861 | |||
8e171c89a6 | |||
5283401fb0 | |||
0b13c31b07 | |||
e72b2fd732 | |||
edc50c89ee | |||
ec5bb6eba5 | |||
6f2b1c214e | |||
43a415a081 | |||
277e3cfe29 | |||
0c14e6ee4c | |||
6841cb68e5 | |||
970e2798ba | |||
31650eb988 | |||
797f403b0d | |||
65c0e34363 | |||
b5f1b465b0 | |||
6d3c86690f | |||
f5460ee843 | |||
47e0838a1e | |||
b8b3f85b2e | |||
070afd1a9b | |||
53634f23de | |||
dcf35bd556 | |||
bcb56b5e9e | |||
16a5bbacb4 | |||
5f66cf5d2f | |||
1adf86532e | |||
c6bc4a5e97 | |||
f37e109aa1 | |||
2904a1bee7 | |||
5066b0ac38 | |||
f567874c98 | |||
3127749f5c | |||
4d78a15cbd | |||
df9e6eac0b | |||
9b552e9db6 | |||
99fceeb9e4 | |||
88ad4a4ee1 | |||
ba0e977e42 | |||
d2c9236c25 | |||
c7256fdc35 | |||
a9ea78e9e7 | |||
0c3c4bceb6 | |||
7e86bcc417 | |||
22ea36ffd2 | |||
d21697b289 | |||
12b6a07e9f | |||
ed06b376f2 | |||
fd3a907d9f | |||
58e6577134 | |||
cf0dd395f0 | |||
6950ac8c42 | |||
7958d0ce19 | |||
1bd8012f10 | |||
621a1c24e4 | |||
3b310d3e19 | |||
4c92ab4dee | |||
97abb69301 | |||
b1eb7f1c65 | |||
c09a34ebe4 | |||
7f9fed74e1 | |||
731d17581b | |||
0b575e044e | |||
5363693b07 | |||
69f9f8e493 | |||
4a7923ce4e | |||
23637b020e | |||
605e66a005 | |||
5ff8e34d2c | |||
00df1c9b85 | |||
7d23984220 | |||
aba535d700 | |||
203f158f5b | |||
e274c90f9d | |||
bf25c6edc8 | |||
2c467c8378 | |||
bdadae6ba5 | |||
1087d402f2 | |||
dc97c0d0df | |||
8b8afdd59b | |||
4dd8f098ac | |||
16b6e1905a | |||
22d1d56ebd | |||
0217702b8c | |||
81d68aeb83 | |||
0e23721f2d | |||
3a771b3da2 | |||
bacb815ecc | |||
f34d9efdb2 | |||
8efb863d5d | |||
d7ca1dd333 | |||
ddc2745495 | |||
12c4c73535 | |||
3326fcdb2d | |||
fba8eaef80 | |||
15a70555b2 | |||
83e196d69f | |||
c86f5d7cde | |||
8d7d177ce3 | |||
cd7b4e6de4 | |||
79adcb520b | |||
41f2a40a58 | |||
9b663f15d9 | |||
ed9d3e2545 | |||
ba7cd6d66e | |||
660bf40a3c | |||
25ba84a7e2 | |||
6566771834 | |||
2d2a2f8c1b | |||
329f266cea | |||
dce1ba57f3 | |||
d3f08d4f96 | |||
ddb63509af | |||
96098b3f2d | |||
256139c9d6 | |||
fd5b681bc6 | |||
2a38890c5f | |||
2ec2a34f51 | |||
10e320911a | |||
9699880581 | |||
13b9f910e1 | |||
acaba76cda | |||
927a820aec | |||
3b9f66a765 | |||
5d2ad006a4 | |||
aa03717f24 | |||
ab5f39b8bb | |||
e1b8edb437 | |||
a78e6f9b29 | |||
047f9c75f5 | |||
159715ebaa | |||
f617567e03 | |||
10a7a9d5e8 | |||
76ed9570c9 | |||
4bc8e4caea | |||
1a054b54c9 | |||
76a9fa4fa2 | |||
4c85686aad | |||
a686340407 | |||
16c7cf1889 | |||
15b33422d0 | |||
649f67697a | |||
125e28160d | |||
eb860ee4b7 | |||
a8c69206fe | |||
26745b4064 | |||
962f68b1d6 | |||
cc5560fc86 | |||
5d65697697 | |||
749d12591e | |||
98f0dab87e | |||
17c87b78a6 | |||
ecbe1c0f39 | |||
9507587652 | |||
dba40c756b | |||
fd9e5dc935 | |||
2816d8b569 | |||
64233b0ccc | |||
9e1b3719d6 | |||
6086b59301 | |||
c345426299 | |||
05216162ef | |||
13e2b23ace | |||
820f0924f9 | |||
5b6aab575e | |||
bd529442ed | |||
33938c20eb | |||
71c490d0ae | |||
4458bb130a | |||
99172bdeb4 | |||
790c75be9c | |||
6a5e1b6bd5 | |||
49e0a6cb1a | |||
b6c7fd7478 | |||
e955d50198 | |||
794d1ee712 | |||
3b5c80e867 | |||
0c4cfdd359 | |||
f263443858 | |||
362a8faa61 | |||
2e361e50ed | |||
0ddeb01502 | |||
64ae333863 | |||
9f2c4b303d | |||
8182be7824 | |||
fa6849374a | |||
115f03cf63 | |||
b6475c3d84 | |||
afd54a1f87 | |||
4f3dd8614d | |||
7989d32834 | |||
0151358635 | |||
8c0e0a7a47 | |||
c570e4868d | |||
6ccd359c93 | |||
ca69e3f2ca | |||
d272450a70 | |||
a21c2a5138 | |||
73273b1643 | |||
4df7aa0f3b | |||
dbe2ee41ae | |||
72a2ef9f96 | |||
e639cd5bbb | |||
3ec93316e0 | |||
ff6a9fc92b | |||
636f5278ad | |||
e10bfe2d37 | |||
4da50dfad5 | |||
dc281902a5 | |||
4903bb9971 | |||
ba702bc9a8 | |||
c7804d390f | |||
9584adcc87 | |||
7154d8cb91 | |||
36b4f2ded5 | |||
1aed3f692c | |||
fdcb1a4014 | |||
384c47c710 | |||
e8d210e15f | |||
6df2745652 | |||
09b5bd2a1f | |||
67ce096aeb | |||
cad7531058 | |||
8dccb584b4 | |||
50eba7ee31 | |||
494693cc63 | |||
05623cffc4 | |||
fed2af8c69 | |||
78f1cf835d | |||
d2283a5b4e | |||
8dd8ee4b9c | |||
6dfbbdf57f | |||
d57166f64b | |||
2799fe1b44 | |||
330e0e2d5f | |||
135d9d5016 | |||
db9f4a1d04 | |||
6b8ab52854 | |||
4e93de2cd2 | |||
a769f8aa87 | |||
e0a38be97b | |||
100de7b160 | |||
9f7e5dd6dd | |||
a9ac7ae480 | |||
2e75680ed7 | |||
c02dbe4eca | |||
f3a08f6812 | |||
e876f90e6c | |||
dde52c1971 | |||
f194aa8d5d | |||
b18b889750 | |||
0aafc18ac7 | |||
fa792f6a67 | |||
53a1e99675 | |||
bda139f390 | |||
ff7028d1fc | |||
fa350edaae | |||
55e6c0ba82 | |||
f5a350f2cc | |||
c079e09860 | |||
99f8e0eec5 | |||
3aec7fdeda | |||
814d8cc83d | |||
bc694d7457 | |||
66d70075ec | |||
8f4dd8580c | |||
7dd845a83b | |||
7b024f4a72 | |||
f1215f3295 | |||
8e17806405 | |||
fb98c0390e | |||
f418c49e63 | |||
a34e872511 | |||
69a07aeec6 | |||
7addf0d5b5 | |||
a001f96b21 | |||
4a26017f2a | |||
0f48910aff | |||
c68efb346c | |||
36f287d569 | |||
4d7e28c09f | |||
c1342195f6 | |||
1fd003c1ec | |||
36d475eaf9 | |||
9180a0036d | |||
f28ec96709 | |||
16baf48b2e | |||
caef0aa400 | |||
fefdbc646f | |||
44cd12a0a0 | |||
07cef29616 | |||
a426df57d7 | |||
a2f8174330 | |||
b6025c6e4a | |||
ceb5159770 | |||
f77dd3134b | |||
c381104505 | |||
d61f1279c1 | |||
0f34fb03a0 | |||
ef6212f4ec | |||
fcc9f8fe8e | |||
8877b36625 | |||
435eeea15f | |||
15af71d448 | |||
27262bde51 | |||
7bf228954c | |||
071feccd32 | |||
f1b817b520 | |||
e6cfff69eb | |||
5fc55ec164 | |||
7211f210dc | |||
fdd40d4492 | |||
6a69cfcf07 | |||
ab51d551d3 | |||
f6b751c4bd | |||
f23deebe80 | |||
b362f80d40 | |||
f634a52e86 | |||
441c2a32cd | |||
bee5484d46 | |||
342283ffea | |||
cb24c90f0c | |||
1824c065f0 | |||
9e4c2866a9 | |||
97fe858760 | |||
ca9d11c692 | |||
c05d6550cb | |||
6e9c399930 | |||
7c6895aec2 | |||
a9e4bc1dbd | |||
5f4e9d9cfb | |||
c4fe384b56 | |||
b2cf633bdc | |||
13ecca61bc | |||
6277678a8e | |||
cafad767a9 | |||
18ba02c2bb | |||
85ffe77a32 | |||
95bebfb814 | |||
1b68e65005 | |||
979e35d979 | |||
d4711abba8 | |||
d53114b723 | |||
a4846ef882 | |||
00afac796e | |||
42c0cc6dd4 | |||
221aee23d1 | |||
c3a5d3c7a5 | |||
a7610aa0c9 | |||
fb4a209a34 | |||
9ba4f5f3df | |||
745c8ca611 | |||
2f007fcb36 | |||
7e30dbfc5a | |||
1ce6ec4a3a | |||
750b897ef0 | |||
c6555dd8f5 | |||
c09d8e6da6 | |||
9d65aa1c40 | |||
59d3e7296b | |||
9a752c6130 | |||
ce27ad5159 | |||
1f3c3fe622 | |||
ff755e7204 | |||
4a2402171a | |||
8d54a56590 | |||
dae337de09 | |||
adaf3f20d7 | |||
de33492cde | |||
1b1ef5a31d | |||
b02b2a40e7 | |||
94848398c0 | |||
c1f49bab3b | |||
4778a57c53 | |||
ea923c391a | |||
0aec5f2981 | |||
59a8cfc0d4 | |||
99eeb27688 | |||
336c599741 | |||
f095e04165 | |||
409c086581 | |||
0f1d433d5b | |||
deed90b65e | |||
ab08d66af3 | |||
3acd08b34b | |||
d187efea4d | |||
ed5eb49b18 | |||
c9fc338174 | |||
8c6c78ed4e | |||
2dea8b0f60 | |||
0160a98e67 | |||
84b87f4eb5 | |||
4c70280527 | |||
178a0305c5 | |||
fcf9c50220 | |||
17bac86aae | |||
d9e502ee5f | |||
17fc8e7161 | |||
e405092ab0 | |||
c6d22a1eb0 | |||
8265834404 | |||
592b52df5e | |||
4d62e6003f | |||
77f44ce5a2 | |||
5ecd7455ac | |||
bb951e0538 | |||
1677d40e91 | |||
4c0d113956 | |||
ae338b8f2c | |||
d5eda47306 | |||
9a0442b60c | |||
c4c571f7e3 | |||
81c86161a7 | |||
003c72a396 | |||
13f77b4428 | |||
80f5923e90 | |||
165e83b692 | |||
e1b2beea4e | |||
bab1cf96c6 | |||
aafc0b0be2 | |||
915e24a0c2 | |||
7d7c19b628 | |||
f6ce7ca8ce | |||
e29f13980b | |||
90d0a6952c | |||
91ff41856b | |||
229328e869 | |||
ad2c080145 | |||
6869e12e4d | |||
0e3fb8d620 | |||
221aa948e4 | |||
9270f41c65 | |||
3d5cb04093 | |||
15df1d819c | |||
11f16316b1 | |||
56ab215db0 | |||
13214d9ac5 | |||
c67bd685a2 | |||
d20c4fee8c | |||
ba982ebf64 | |||
5bd74c3064 | |||
5cdc9db76c | |||
de02cc26f9 | |||
35a1a1f7d7 | |||
54d3702513 | |||
c3f9764e0a | |||
ab4096e720 | |||
26fa325ee4 | |||
314027631a | |||
6e09b56c29 | |||
08f541a7a8 | |||
26412b4793 | |||
9ea689d7e4 | |||
f3b994f845 | |||
46906c7f65 | |||
4daed7c4a9 | |||
ebb94ee212 | |||
18a592ad28 | |||
ba48efbc52 | |||
0513a4eb2f | |||
254852ee36 | |||
ef6d76c22d | |||
66c3ead5d6 | |||
908a6b336b | |||
373e401671 | |||
06d008d6c6 | |||
11c9444b6c | |||
ff284b3f51 | |||
628e935fe5 | |||
13641fcbae | |||
595b877a24 | |||
17d1d2e8a6 | |||
c1b3d3341e | |||
725b6515ff | |||
61a535f3ac | |||
7c312a33d9 | |||
b7d369dbb6 | |||
16cbb18f15 | |||
4f83818ff8 | |||
9e383a3b9e | |||
a9b7d8250e | |||
1ec94d9226 | |||
c1607eeac4 | |||
8927e3df9f | |||
7458223cc0 | |||
5a0b597e3f | |||
bf20758906 | |||
1bfd7b5a5f | |||
aa813303a4 | |||
9baf20e907 | |||
1947c3a25d | |||
6b22dadcdd | |||
4efccd15b3 | |||
496fb67c29 | |||
bc97bdfa71 | |||
68784d8703 | |||
10c01ebc83 | |||
6c22b98235 | |||
62bd5963d0 | |||
726cd2664d | |||
5378638ba7 | |||
347aa3fe0c | |||
c9478cc15e | |||
ce0d783e82 | |||
5057fe48ab | |||
fcc755a5b8 | |||
ab8127f980 | |||
dad50348db | |||
140ff9ade4 | |||
2a64a0d3b1 | |||
82983cd7c1 | |||
b31e882582 | |||
dd80b2fc88 | |||
3051fc1987 | |||
e54be83b27 | |||
448aac8880 | |||
db4522bbdc | |||
d7c34f05e4 | |||
b96fbd5bd8 | |||
25d5a2afe4 | |||
66515523c1 | |||
684cfd0cd2 | |||
a0e745c54a | |||
a239d54bd7 | |||
c98dd9b0a7 | |||
193d674852 | |||
15e37555ae | |||
d337722920 | |||
5af92d13fe | |||
114307a679 | |||
99ca953b1d | |||
b837cc134d | |||
d3ee0b72e4 | |||
6914e2f7e2 | |||
37017119b0 | |||
447d2365c7 | |||
ece61a1860 | |||
acc6bdd95c | |||
559811e8ef |
@ -1,2 +1,6 @@
|
||||
Joe Neeman
|
||||
Philippe Rouquier
|
||||
Philippe Rouquier
|
||||
Gabriel Craciunescu
|
||||
George Danchev
|
||||
Jean-Francois Wauthy
|
||||
Lorenzo Taylor
|
||||
|
@ -1,13 +1,12 @@
|
||||
Derek Foreman <derek@signalmarketing.com> and Ben Jansens <xor@orodu.net>
|
||||
Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
|
||||
Mario Danic <mario.danic@gmail.com>, Thomas Schmitt <scdbackup@gmx.net>
|
||||
Copyright (C) 2006 Mario Danic, Thomas Schmitt
|
||||
Copyright (C) 2006-2011 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 or later
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
|
303
ChangeLog
Normal file
303
ChangeLog
Normal file
@ -0,0 +1,303 @@
|
||||
|
||||
libburn-1.1.0.pl01.tar.gz Mon Jun 20 2011
|
||||
===============================================================================
|
||||
* Bug fix: libburn-1.1.0 compiled only on Linux, FreeBSD, and Solaris
|
||||
|
||||
libburn-1.1.0.tar.gz Sat Jun 18 2011
|
||||
===============================================================================
|
||||
* Bug fix: burn_disc_format() on DVD-RW issued wrong block size with type 00h
|
||||
* New API call burn_disc_next_track_is_damaged()
|
||||
* New API call burn_disc_close_damaged()
|
||||
* Dropped suffix .plXY from tarball name
|
||||
|
||||
Release 1.0.8 was skipped to get back in sync with libisofs and libisoburn.
|
||||
|
||||
libburn-1.0.6.pl00.tar.gz Sat Apr 9 2011
|
||||
===============================================================================
|
||||
* Burning DVD-R DAO with 2 kB size granularity rather than 32 kB
|
||||
* New API call burn_allow_drive_role_4()
|
||||
|
||||
libburn-1.0.4.pl00.tar.gz Thu Mar 3 2011
|
||||
===============================================================================
|
||||
* Bug fix: Read-only file descriptors were classified as write-only pseudo
|
||||
drives
|
||||
|
||||
libburn-1.0.2.pl00.tar.gz Wed Feb 23 2011
|
||||
===============================================================================
|
||||
* Removed compilation obstacles on Solaris 9.
|
||||
* Improved recognition of non-seekable stdio pseudo-drives.
|
||||
|
||||
libburn-1.0.0.pl00.tar.gz Sun Jan 16 2011
|
||||
===============================================================================
|
||||
* Allowed umask to create stdio-drive files with rw-permissions for all
|
||||
* cdrskin now refuses to burn if the foreseeable size exceeds media capacity
|
||||
|
||||
libburn-0.9.0.pl00.tar.gz Wed Dec 08 2010
|
||||
===============================================================================
|
||||
* Regression fix: SCSI reply data logging was disabled in release 0.8.6
|
||||
|
||||
libburn-0.8.8.pl00.tar.gz Wed Oct 20 2010
|
||||
===============================================================================
|
||||
* New API call burn_offst_source_new()
|
||||
* New API call burn_disc_get_bd_spare_info()
|
||||
|
||||
libburn-0.8.6.pl00.tar.gz Fri Sep 17 2010
|
||||
===============================================================================
|
||||
* Lifted test reservation on DVD-R DL media.
|
||||
* Hiding all non-API symbols from the linker by use of --version-script
|
||||
* Now with history of release notes in ./ChangeLog file.
|
||||
|
||||
libburn-0.8.4.pl00.tar.gz Wed Jun 30 2010
|
||||
===============================================================================
|
||||
* General POSIX system adapters ignore SIGWINCH and SIGURG if defined
|
||||
* Allowed 64 kB max output buffer size on all OSes
|
||||
|
||||
libburn-0.8.2.pl00.tar.gz Fri Jun 11 2010
|
||||
===============================================================================
|
||||
* New system adapter for Solaris uscsi (tested on snv134, kernel 5.11)
|
||||
* Bug fix: CD TOC was not read if the first track did not start at LBA 0
|
||||
* Bug fix: CD-ROM media got attributed random lead-in and lead-out adresses
|
||||
* Bug fix: SIGSEGV of experimental libcdio system adapter if drive list is
|
||||
empty
|
||||
|
||||
libburn-0.8.0.pl00.tar.gz Fri Apr 09 2010
|
||||
===============================================================================
|
||||
* libburn now works with ahci driver on FreeBSD 8-STABLE.
|
||||
|
||||
libburn-0.7.8.pl00.tar.gz Wed Mar 10 2010
|
||||
===============================================================================
|
||||
* Bug fix: On FreeBSD, piped input was falsely attributed a small fixed size.
|
||||
* Built-in abort handling is more suitable for FreeBSD now.
|
||||
cdrskin novelties:
|
||||
* Bug fix: Option fs=0 led to SIGSEGV. Regression introduced by version 0.7.4
|
||||
in december 2009.
|
||||
* Abort handling is more suitable for FreeBSD now.
|
||||
|
||||
libburn-0.7.6.pl00.tar.gz Sat Jan 23 2010
|
||||
===============================================================================
|
||||
* Bug fix: System adapter for generic X/Open was missing in libburn release
|
||||
tarball
|
||||
* Bug fix: with non-Linux adapters there were 0 readable bytes on block devices
|
||||
* Made FreeBSD system adapter safe from mutal burn spoiling and drive deadlock
|
||||
* Enabled FreeBSD system adapter for Debian kfreebsd
|
||||
* Experimental SCSI transport adapter via GNU libcdio 0.83git
|
||||
cdrskin novelties:
|
||||
* none
|
||||
|
||||
libburn-0.7.4.pl01.tar.gz Sat Dec 26 2009
|
||||
===============================================================================
|
||||
* Bug fix: Added missing system adapter for generic X/Open to libburn release
|
||||
tarball
|
||||
|
||||
Libburn 0.7.4.pl00 Mon Dec 07 2009
|
||||
===============================================================================
|
||||
* Bug fix: SIGSEGV from NULL pointer with media product id inquiry on LG
|
||||
GH22LS30
|
||||
* Bug fix: DVD DAO track size was rounded up much too generously
|
||||
* Workaround for Pioneer DVR-216D which got stuck on DVD-R burns.
|
||||
(already fixed in 0.7.2.pl01)
|
||||
* Workaround for Pioneer DVR-216D refusal to eject.
|
||||
(already fixed in 0.7.2.pl01)
|
||||
* Configure options --enable-dvd-obs-64k, --enable-track-src-odirect
|
||||
* New API calls burn_write_opts_set_dvd_obs(),
|
||||
burn_write_opts_set_stdio_fsync()
|
||||
* New API call burn_set_scsi_logging()
|
||||
* New API calls burn_fifo_get_statistics(), burn_fifo_next_interval(),
|
||||
burn_fifo_fill()
|
||||
* Re-implemented ECMA-130 P-parity, Q-parity and scrambling for BURN_WRITE_RAW
|
||||
cdrskin novelties:
|
||||
* cdrskin option -V for logging of SCSI commands
|
||||
* New cdrskin options dvd_obs= and stdio_fsync=
|
||||
* New compile_cdrskin.sh option -dvd_obs_64k
|
||||
|
||||
libburn-0.7.2.pl01.tar.gz Fri Nov 13 2009
|
||||
===============================================================================
|
||||
* Workaround for Pioneer DVR-216D which got stuck on DVD-R burns.
|
||||
* Workaround for Pioneer DVR-216D refusal to eject.
|
||||
|
||||
Libburn 0.7.2.pl00 Mon Oct 12 2009
|
||||
===============================================================================
|
||||
* Bug fix: CD TAO sessions with multiple tracks did not work in -dummy mode
|
||||
* New API calls burn_get_media_product_id() , burn_guess_manufacturer() ,
|
||||
burn_guess_cd_manufacturer()
|
||||
* New API call burn_disc_get_cd_info()
|
||||
* New API call burn_track_set_cdxa_conv()
|
||||
cdrskin novelties:
|
||||
* Better interpretation of options -mode2, -xa, -xa1, -xa2
|
||||
* New option --xa1-ignore
|
||||
* New -atip report lines "Product Id:" and "Producer:"
|
||||
|
||||
libburn-0.7.0.pl00.tar.gz Thu Aug 27 2009
|
||||
===============================================================================
|
||||
* New API calls burn_drive_get_all_profiles(), burn_obtain_profile_name() allow
|
||||
to inquire and process the list of supported media types. cdrskin lists all
|
||||
supported profiles with option -atip -v
|
||||
* New API call burn_drive_snooze() allows to calm down a drive when no i/o is
|
||||
expected for a while.
|
||||
* Bug fix: Some SCSI commands stalled on U3 memory sticks which appear as a hub
|
||||
with a memory stick and a CD-ROM drive containing a small CD. These commands
|
||||
make not much sense with a CD-ROM and are now avoided for this media
|
||||
situation.
|
||||
|
||||
libburn-0.6.8.pl00.tar.gz Tue Jul 14 2009
|
||||
===============================================================================
|
||||
* Bug fix: Old MMC-1 drives were rejected because of mode page 2Ah length.
|
||||
* cdrskin -scanbus now works with high SCSI bus numbers.
|
||||
|
||||
libburn-0.6.6.pl00.tar.gz Fri May 8 2009
|
||||
===============================================================================
|
||||
* Bug fix: Improper abort handling with broken pipe during outputto a stdio:
|
||||
pseudo-drive.
|
||||
* Bug fix: Device scan stalled on FreeBSD with non-burner USB device
|
||||
|
||||
libburn-0.6.4.pl00.tar.gz Fri Mar 13 2009
|
||||
===============================================================================
|
||||
* New operating system adapter "dummy" for stdio on general X/Open systems
|
||||
* New API function burn_drive_set_stream_recording() allows to write the
|
||||
crucial start blocks of a filesystem with slow BD-RE Defect Management and to
|
||||
write the bulk of data with full nominal speed.
|
||||
|
||||
libburn-0.6.2.pl00.tar.gz Fri Feb 20 2009
|
||||
===============================================================================
|
||||
* Improvements with build system for FreeBSD
|
||||
|
||||
libburn-0.6.0.pl01.tar.gz Wed Jan 07 2009
|
||||
===============================================================================
|
||||
* Bug fix: BD-R were not correctly finalized
|
||||
|
||||
libburn-0.6.0.pl00.tar.gz Sun Jan 04 2009
|
||||
===============================================================================
|
||||
* Formatting and writing of BD-R media
|
||||
* New API function burn_get_read_capacity()
|
||||
|
||||
libburn-0.5.8.pl00.tar.gz Mon Dec 08 2008
|
||||
===============================================================================
|
||||
* Bug fix: A session without leadout entry on CD caused a SIGSEGV by NULL
|
||||
* Improvements about BD-RE formatting
|
||||
|
||||
libburn-0.5.6.pl00.tar.gz Wed Nov 12 2008
|
||||
===============================================================================
|
||||
* Bug fix: libburn fifo thread was not aborted when burn run was aborted which
|
||||
could lead to use of freed memory.
|
||||
|
||||
libburn-0.5.4.pl00.tar.gz Mon Oct 6 2008
|
||||
===============================================================================
|
||||
* Bug fix: On Linux 2.4 /dev/sr0 was accepted as enumerable address but then
|
||||
failed to work.
|
||||
|
||||
libburn-0.5.2.pl00.tar.gz Wed Aug 20 2008
|
||||
===============================================================================
|
||||
* Larger set of possibly acceptable drive device file names
|
||||
|
||||
libburn-0.5.0.pl00.tar.gz Thu Jul 17 2008
|
||||
===============================================================================
|
||||
* Bug fix: cdrskin option drive_scsi_dev_family=scd lead to buffer overflow
|
||||
* Ability to use /dev/scd as fallback if /dev/sr does not exist
|
||||
* New API call burn_fifo_peek_data()
|
||||
|
||||
libburn-0.4.8.pl00.tar.gz Sat May 17 2008
|
||||
===============================================================================
|
||||
* Bug fix: Random access addressing for DVD-RAM and BD-RE did not work.
|
||||
* cdrskin: Affected were options write_start_address= and
|
||||
-- grow_overwriteable_iso on DVD-RAM or BD-RE.
|
||||
* xorriso: Affected were sessions on DVD-RAM or BD-RE after the first one.
|
||||
|
||||
libburn-0.4.6.pl00.tar.gz Sun May 11 2008
|
||||
===============================================================================
|
||||
* Support for BD-RE media is now official
|
||||
* New burn_write_opts_set_stream_recording() can speed up DVD-RAM and BD-RE
|
||||
* New cdrskin option --list_formats
|
||||
* New cdrskin blank types for expert formatting of DVD-RAM and BD-RE
|
||||
* New cdrskin blank type blank=as_needed for automatic handling of media
|
||||
|
||||
libburn-0.4.4.tar.gz Thu April 10 2008
|
||||
===============================================================================
|
||||
* Support for DVD+R/DL media is now official
|
||||
|
||||
libburn-0.4.2.tar.gz Sun Feb 3 2008
|
||||
===============================================================================
|
||||
* Long term commitment to ABI libburn.so.4.
|
||||
* ABI compatibility is guaranteed for any older feature set released since
|
||||
libburn-0.3.2 about one year ago.
|
||||
* libburn provides means for compile time and runtime checking of its version.
|
||||
* Compile time check in cdrskin for proper version of libburn include file.
|
||||
Required is at least 0.4.2.
|
||||
* Runtime check in cdrskin prevents dynamic linking with outdated version of
|
||||
libburn.so.4. Required is at least the version seen in the include file at
|
||||
compile time.
|
||||
|
||||
libburn-0.4.0.tar.gz Mon Oct 29 2007
|
||||
===============================================================================
|
||||
* New option direct_write_amount=
|
||||
* New option --grow_overwriteable_iso
|
||||
* New option --allow_emulated_drives dev=stdio:<path>
|
||||
* More cdrecord options supported: -format, -inq, -load, -lock, -immed, -waiti
|
||||
* New option fallback_program=
|
||||
* A lot of libburn API additions.
|
||||
|
||||
libburn-0.3.8.tar.gz Tue Jul 31 2007
|
||||
===============================================================================
|
||||
* Now able to cope with the peculiarities of Linux 2.4 USB
|
||||
* Refusal to perform -dummy runs on media which cannot simulate burning
|
||||
* New option modesty_on_drive= may help with hda -> hdb burns
|
||||
* New option minbuf= , cdrecord compatible frontend of modesty_on_drive=
|
||||
* New option --adjust_speed_to_drive
|
||||
* Precautions against using the burner drive as track source
|
||||
* Note: ABI has not been broken.
|
||||
|
||||
libburn-0.3.6.tar.gz Thu Apr 26 2007
|
||||
===============================================================================
|
||||
* On Linux kernel 2.6, /dev/sr* gets used rather than /dev/sg*.
|
||||
* DVD+R now get finalized (if not -multi is given)
|
||||
|
||||
libburn-0.3.4.tar.gz Mon Mar 12 2007
|
||||
===============================================================================
|
||||
* Multi-session recording on DVD+R, including -toc, -msinfo
|
||||
* Options --tell_media_space , assert_write_lba=
|
||||
* Bug fix of rare multi track fifo stall
|
||||
|
||||
libburn-0.3.2.tar.gz Feb 11 2007
|
||||
===============================================================================
|
||||
* Burnfree enabled by default
|
||||
* Multi-session recording on sequential DVD-R[W], including -toc, -msinfo
|
||||
* DVD-R[W] Disk-at-once recording
|
||||
|
||||
libburn-0.3.0.1.tar.gz Tue Jan 30 2007
|
||||
===============================================================================
|
||||
* Improved recognition of unsuitable media types
|
||||
* Replaced ban of chmod u+s by loud warning
|
||||
* detailed man page for cdrskin
|
||||
* Burning of DVD+RW and DVD-RAM media as single-track TAO-like initial session
|
||||
* Formatting and then burning to DVD-RW like to DVD+RW
|
||||
* New option -msifile=path from cdrkit/wodim
|
||||
* 0.3.0.1 release notes *
|
||||
* Bug fix enabling tracks >= 1.3 GB from disk file
|
||||
|
||||
libburn-0.2.6.3.tar.gz Fri Dec 29 2006
|
||||
===============================================================================
|
||||
* 0.2.6 release notes (Wed Nov 22 2006)
|
||||
* After a lot of time with dedication to this project, we proudly present you
|
||||
libburn 0.2.6. It is the first version of cdrskin and libburn after they have
|
||||
been split from genisofs and libisofs. Main new features are write mode TAO
|
||||
and support for multi session.
|
||||
* 0.2.6.1 release notes (Fri Nov 24 2006)
|
||||
* Point release to fix misleading version numbers in messages and documentation
|
||||
* 0.2.6.2 release notes (Sat Dec 16 2006)
|
||||
* cdrskin man page backported from development version 0.2.7.
|
||||
* 0.2.6.3 release notes (Fri Dec 29 2006)
|
||||
* Point release to fix build system problems people have experienced with the
|
||||
past release.
|
||||
|
||||
libburn-0.2.3.snapshot02.tar.gz Thu Nov 02 2006
|
||||
===============================================================================
|
||||
* Stabilized snapshot including release 0.2.4.pl01 of cdrskin
|
||||
* cdrskin 0.2.4 release notes
|
||||
* Compatibility with cdrecord has been improved in respect to drive addresses,
|
||||
audio extraction from .wav, -scanbus, -toc, drive buffer fill indicator.
|
||||
* Note: The previous snapshot01 with the same source base is handicapped by a
|
||||
broken ./configure setup. It works well on Intel compatible CPUs but is
|
||||
supposed to be unusable on big-endian architectures.
|
||||
|
||||
libburn-0.2.2.tar.gz Wed Sep 20 2006
|
||||
===============================================================================
|
||||
Initial release of libburnia's libburn combined with cdrskin.
|
234
INSTALL
Normal file
234
INSTALL
Normal file
@ -0,0 +1,234 @@
|
||||
Installation Instructions
|
||||
*************************
|
||||
|
||||
Copyright (C) 1994, 1995, 1996, 1999, 2000, 2001, 2002, 2004, 2005,
|
||||
2006 Free Software Foundation, Inc.
|
||||
|
||||
This file is free documentation; the Free Software Foundation gives
|
||||
unlimited permission to copy, distribute and modify it.
|
||||
|
||||
Basic Installation
|
||||
==================
|
||||
|
||||
Briefly, the shell commands `./configure; make; make install' should
|
||||
configure, build, and install this package. The following
|
||||
more-detailed instructions are generic; see the `README' file for
|
||||
instructions specific to this package.
|
||||
|
||||
The `configure' shell script attempts to guess correct values for
|
||||
various system-dependent variables used during compilation. It uses
|
||||
those values to create a `Makefile' in each directory of the package.
|
||||
It may also create one or more `.h' files containing system-dependent
|
||||
definitions. Finally, it creates a shell script `config.status' that
|
||||
you can run in the future to recreate the current configuration, and a
|
||||
file `config.log' containing compiler output (useful mainly for
|
||||
debugging `configure').
|
||||
|
||||
It can also use an optional file (typically called `config.cache'
|
||||
and enabled with `--cache-file=config.cache' or simply `-C') that saves
|
||||
the results of its tests to speed up reconfiguring. Caching is
|
||||
disabled by default to prevent problems with accidental use of stale
|
||||
cache files.
|
||||
|
||||
If you need to do unusual things to compile the package, please try
|
||||
to figure out how `configure' could check whether to do them, and mail
|
||||
diffs or instructions to the address given in the `README' so they can
|
||||
be considered for the next release. If you are using the cache, and at
|
||||
some point `config.cache' contains results you don't want to keep, you
|
||||
may remove or edit it.
|
||||
|
||||
The file `configure.ac' (or `configure.in') is used to create
|
||||
`configure' by a program called `autoconf'. You need `configure.ac' if
|
||||
you want to change it or regenerate `configure' using a newer version
|
||||
of `autoconf'.
|
||||
|
||||
The simplest way to compile this package is:
|
||||
|
||||
1. `cd' to the directory containing the package's source code and type
|
||||
`./configure' to configure the package for your system.
|
||||
|
||||
Running `configure' might take a while. While running, it prints
|
||||
some messages telling which features it is checking for.
|
||||
|
||||
2. Type `make' to compile the package.
|
||||
|
||||
3. Optionally, type `make check' to run any self-tests that come with
|
||||
the package.
|
||||
|
||||
4. Type `make install' to install the programs and any data files and
|
||||
documentation.
|
||||
|
||||
5. You can remove the program binaries and object files from the
|
||||
source code directory by typing `make clean'. To also remove the
|
||||
files that `configure' created (so you can compile the package for
|
||||
a different kind of computer), type `make distclean'. There is
|
||||
also a `make maintainer-clean' target, but that is intended mainly
|
||||
for the package's developers. If you use it, you may have to get
|
||||
all sorts of other programs in order to regenerate files that came
|
||||
with the distribution.
|
||||
|
||||
Compilers and Options
|
||||
=====================
|
||||
|
||||
Some systems require unusual options for compilation or linking that the
|
||||
`configure' script does not know about. Run `./configure --help' for
|
||||
details on some of the pertinent environment variables.
|
||||
|
||||
You can give `configure' initial values for configuration parameters
|
||||
by setting variables in the command line or in the environment. Here
|
||||
is an example:
|
||||
|
||||
./configure CC=c99 CFLAGS=-g LIBS=-lposix
|
||||
|
||||
*Note Defining Variables::, for more details.
|
||||
|
||||
Compiling For Multiple Architectures
|
||||
====================================
|
||||
|
||||
You can compile the package for more than one kind of computer at the
|
||||
same time, by placing the object files for each architecture in their
|
||||
own directory. To do this, you can use GNU `make'. `cd' to the
|
||||
directory where you want the object files and executables to go and run
|
||||
the `configure' script. `configure' automatically checks for the
|
||||
source code in the directory that `configure' is in and in `..'.
|
||||
|
||||
With a non-GNU `make', it is safer to compile the package for one
|
||||
architecture at a time in the source code directory. After you have
|
||||
installed the package for one architecture, use `make distclean' before
|
||||
reconfiguring for another architecture.
|
||||
|
||||
Installation Names
|
||||
==================
|
||||
|
||||
By default, `make install' installs the package's commands under
|
||||
`/usr/local/bin', include files under `/usr/local/include', etc. You
|
||||
can specify an installation prefix other than `/usr/local' by giving
|
||||
`configure' the option `--prefix=PREFIX'.
|
||||
|
||||
You can specify separate installation prefixes for
|
||||
architecture-specific files and architecture-independent files. If you
|
||||
pass the option `--exec-prefix=PREFIX' to `configure', the package uses
|
||||
PREFIX as the prefix for installing programs and libraries.
|
||||
Documentation and other data files still use the regular prefix.
|
||||
|
||||
In addition, if you use an unusual directory layout you can give
|
||||
options like `--bindir=DIR' to specify different values for particular
|
||||
kinds of files. Run `configure --help' for a list of the directories
|
||||
you can set and what kinds of files go in them.
|
||||
|
||||
If the package supports it, you can cause programs to be installed
|
||||
with an extra prefix or suffix on their names by giving `configure' the
|
||||
option `--program-prefix=PREFIX' or `--program-suffix=SUFFIX'.
|
||||
|
||||
Optional Features
|
||||
=================
|
||||
|
||||
Some packages pay attention to `--enable-FEATURE' options to
|
||||
`configure', where FEATURE indicates an optional part of the package.
|
||||
They may also pay attention to `--with-PACKAGE' options, where PACKAGE
|
||||
is something like `gnu-as' or `x' (for the X Window System). The
|
||||
`README' should mention any `--enable-' and `--with-' options that the
|
||||
package recognizes.
|
||||
|
||||
For packages that use the X Window System, `configure' can usually
|
||||
find the X include and library files automatically, but if it doesn't,
|
||||
you can use the `configure' options `--x-includes=DIR' and
|
||||
`--x-libraries=DIR' to specify their locations.
|
||||
|
||||
Specifying the System Type
|
||||
==========================
|
||||
|
||||
There may be some features `configure' cannot figure out automatically,
|
||||
but needs to determine by the type of machine the package will run on.
|
||||
Usually, assuming the package is built to be run on the _same_
|
||||
architectures, `configure' can figure that out, but if it prints a
|
||||
message saying it cannot guess the machine type, give it the
|
||||
`--build=TYPE' option. TYPE can either be a short name for the system
|
||||
type, such as `sun4', or a canonical name which has the form:
|
||||
|
||||
CPU-COMPANY-SYSTEM
|
||||
|
||||
where SYSTEM can have one of these forms:
|
||||
|
||||
OS KERNEL-OS
|
||||
|
||||
See the file `config.sub' for the possible values of each field. If
|
||||
`config.sub' isn't included in this package, then this package doesn't
|
||||
need to know the machine type.
|
||||
|
||||
If you are _building_ compiler tools for cross-compiling, you should
|
||||
use the option `--target=TYPE' to select the type of system they will
|
||||
produce code for.
|
||||
|
||||
If you want to _use_ a cross compiler, that generates code for a
|
||||
platform different from the build platform, you should specify the
|
||||
"host" platform (i.e., that on which the generated programs will
|
||||
eventually be run) with `--host=TYPE'.
|
||||
|
||||
Sharing Defaults
|
||||
================
|
||||
|
||||
If you want to set default values for `configure' scripts to share, you
|
||||
can create a site shell script called `config.site' that gives default
|
||||
values for variables like `CC', `cache_file', and `prefix'.
|
||||
`configure' looks for `PREFIX/share/config.site' if it exists, then
|
||||
`PREFIX/etc/config.site' if it exists. Or, you can set the
|
||||
`CONFIG_SITE' environment variable to the location of the site script.
|
||||
A warning: not all `configure' scripts look for a site script.
|
||||
|
||||
Defining Variables
|
||||
==================
|
||||
|
||||
Variables not defined in a site shell script can be set in the
|
||||
environment passed to `configure'. However, some packages may run
|
||||
configure again during the build, and the customized values of these
|
||||
variables may be lost. In order to avoid this problem, you should set
|
||||
them in the `configure' command line, using `VAR=value'. For example:
|
||||
|
||||
./configure CC=/usr/local2/bin/gcc
|
||||
|
||||
causes the specified `gcc' to be used as the C compiler (unless it is
|
||||
overridden in the site shell script).
|
||||
|
||||
Unfortunately, this technique does not work for `CONFIG_SHELL' due to
|
||||
an Autoconf bug. Until the bug is fixed you can use this workaround:
|
||||
|
||||
CONFIG_SHELL=/bin/bash /bin/bash ./configure CONFIG_SHELL=/bin/bash
|
||||
|
||||
`configure' Invocation
|
||||
======================
|
||||
|
||||
`configure' recognizes the following options to control how it operates.
|
||||
|
||||
`--help'
|
||||
`-h'
|
||||
Print a summary of the options to `configure', and exit.
|
||||
|
||||
`--version'
|
||||
`-V'
|
||||
Print the version of Autoconf used to generate the `configure'
|
||||
script, and exit.
|
||||
|
||||
`--cache-file=FILE'
|
||||
Enable the cache: use and save the results of the tests in FILE,
|
||||
traditionally `config.cache'. FILE defaults to `/dev/null' to
|
||||
disable caching.
|
||||
|
||||
`--config-cache'
|
||||
`-C'
|
||||
Alias for `--cache-file=config.cache'.
|
||||
|
||||
`--quiet'
|
||||
`--silent'
|
||||
`-q'
|
||||
Do not print messages saying which checks are being made. To
|
||||
suppress all normal output, redirect it to `/dev/null' (any error
|
||||
messages will still be shown).
|
||||
|
||||
`--srcdir=DIR'
|
||||
Look for the package's source code in directory DIR. Usually
|
||||
`configure' can determine that directory automatically.
|
||||
|
||||
`configure' also accepts some other, not widely useful, options. Run
|
||||
`configure --help' for more details.
|
||||
|
120
Makefile.am
120
Makefile.am
@ -1,13 +1,21 @@
|
||||
pkgconfigdir=$(libdir)/pkgconfig
|
||||
|
||||
# ts A90315 : LIBBURNIA_PKGCONFDIR is defined OS specific in acinclude.m4
|
||||
# was: pkgconfigdir=$(libdir)/pkgconfig
|
||||
pkgconfigdir=$(LIBBURNIA_PKGCONFDIR)
|
||||
|
||||
libincludedir=$(includedir)/libburn
|
||||
|
||||
lib_LTLIBRARIES = libburn/libburn.la libisofs/libisofs.la
|
||||
lib_LTLIBRARIES = libburn/libburn.la
|
||||
ACLOCAL_AMFLAGS = -I ./
|
||||
|
||||
## ========================================================================= ##
|
||||
|
||||
# Build libraries
|
||||
libburn_libburn_la_LDFLAGS = \
|
||||
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
|
||||
# This causes undesired .o names
|
||||
# configure.ac appends -D options to variable CFLAG
|
||||
### libburn_libburn_la_CFLAGS = $(LIBBURN_DVD_OBS_64K)
|
||||
libburn_libburn_la_LIBADD = $(LIBBURN_ARCH_LIBS) $(THREAD_LIBS)
|
||||
libburn_libburn_la_SOURCES = \
|
||||
libburn/async.c \
|
||||
@ -21,13 +29,13 @@ libburn_libburn_la_SOURCES = \
|
||||
libburn/debug.h \
|
||||
libburn/drive.c \
|
||||
libburn/drive.h \
|
||||
libburn/ecma130ab.c \
|
||||
libburn/ecma130ab.h \
|
||||
libburn/error.h \
|
||||
libburn/file.c \
|
||||
libburn/file.h \
|
||||
libburn/init.c \
|
||||
libburn/init.h \
|
||||
libburn/lec.c \
|
||||
libburn/lec.h \
|
||||
libburn/libburn.h \
|
||||
libburn/libdax_audioxtr.h \
|
||||
libburn/libdax_audioxtr.c \
|
||||
@ -39,6 +47,7 @@ libburn_libburn_la_SOURCES = \
|
||||
libburn/null.h \
|
||||
libburn/options.c \
|
||||
libburn/options.h \
|
||||
libburn/os.h \
|
||||
libburn/read.c \
|
||||
libburn/read.h \
|
||||
libburn/sbc.c \
|
||||
@ -64,77 +73,60 @@ libburn_libburn_la_SOURCES = \
|
||||
|
||||
## libburn/sg-@ARCH@.c \
|
||||
|
||||
libisofs_libisofs_la_LDFLAGS = \
|
||||
-version-info $(LT_CURRENT):$(LT_REVISION):$(LT_AGE)
|
||||
libisofs_libisofs_la_SOURCES = \
|
||||
libisofs/tree.h \
|
||||
libisofs/tree.c \
|
||||
libisofs/volume.h \
|
||||
libisofs/volume.c \
|
||||
libisofs/util.h \
|
||||
libisofs/util.c \
|
||||
libisofs/ecma119.c \
|
||||
libisofs/ecma119.h \
|
||||
libisofs/ecma119_tree.c \
|
||||
libisofs/ecma119_tree.h \
|
||||
libisofs/susp.h \
|
||||
libisofs/susp.c \
|
||||
libisofs/rockridge.h \
|
||||
libisofs/rockridge.c \
|
||||
libisofs/joliet.c \
|
||||
libisofs/joliet.h \
|
||||
libisofs/exclude.c \
|
||||
libisofs/exclude.h \
|
||||
libisofs/hash.h \
|
||||
libisofs/hash.c
|
||||
|
||||
libinclude_HEADERS = \
|
||||
libburn/libburn.h \
|
||||
libisofs/libisofs.h
|
||||
libburn/libburn.h
|
||||
|
||||
install-exec-hook:
|
||||
$(LIBBURNIA_LDCONFIG_CMD) "$(DESTDIR)$(libdir)" || echo 'NOTE: Explicite dynamic library configuration failed. If needed, configure manually for:' "$(DESTDIR)$(libdir)"
|
||||
|
||||
## ========================================================================= ##
|
||||
|
||||
## Build test applications
|
||||
noinst_PROGRAMS = \
|
||||
test/libburner \
|
||||
test/offst_source \
|
||||
test/telltoc \
|
||||
test/dewav \
|
||||
test/fake_au \
|
||||
test/iso \
|
||||
test/poll \
|
||||
test/toc \
|
||||
test/structest
|
||||
|
||||
bin_PROGRAMS = \
|
||||
cdrskin/cdrskin
|
||||
|
||||
LIBBURN_EXTRALIBS = $(LIBBURN_ARCH_LIBS) $(THREAD_LIBS)
|
||||
|
||||
test_libburner_CPPFLAGS = -Ilibburn
|
||||
test_libburner_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
|
||||
test_libburner_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
|
||||
test_libburner_SOURCES = test/libburner.c
|
||||
test_offst_source_CPPFLAGS = -Ilibburn
|
||||
test_offst_source_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
|
||||
test_offst_source_SOURCES = test/offst_source.c
|
||||
test_telltoc_CPPFLAGS = -Ilibburn
|
||||
test_telltoc_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
|
||||
test_telltoc_SOURCES = test/telltoc.c
|
||||
test_dewav_CPPFLAGS = -Ilibburn
|
||||
test_dewav_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
|
||||
test_dewav_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
|
||||
test_dewav_SOURCES = test/dewav.c
|
||||
test_fake_au_CPPFLAGS =
|
||||
test_fake_au_LDADD =
|
||||
test_fake_au_SOURCES = test/fake_au.c
|
||||
test_poll_CPPFLAGS = -Ilibburn
|
||||
test_poll_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
|
||||
test_poll_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
|
||||
test_poll_SOURCES = test/poll.c
|
||||
test_toc_CPPFLAGS = -Ilibburn
|
||||
test_toc_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
|
||||
test_toc_SOURCES = test/toc.c
|
||||
test_structest_CPPFLAGS = -Ilibburn
|
||||
test_structest_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
|
||||
test_structest_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
|
||||
test_structest_SOURCES = test/structest.c
|
||||
test_iso_CPPFLAGS = -Ilibisofs
|
||||
test_iso_LDADD = $(libisofs_libisofs_la_OBJECTS) $(THREAD_LIBS)
|
||||
test_iso_SOURCES = test/iso.c
|
||||
|
||||
## cdrskin construction site - ts A60816
|
||||
## cdrskin construction site - ts A60816 - B10409
|
||||
cdrskin_cdrskin_CPPFLAGS = -Ilibburn
|
||||
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_0_2_3
|
||||
cdrskin_cdrskin_LDADD = $(libburn_libburn_la_OBJECTS) $(THREAD_LIBS)
|
||||
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_1_1_0
|
||||
|
||||
# cdrskin_cdrskin_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
|
||||
# ts A80123, change proposed by Simon Huggins to cause dynamic libburn linking
|
||||
cdrskin_cdrskin_LDADD = libburn/libburn.la $(LIBBURN_EXTRALIBS)
|
||||
|
||||
cdrskin_cdrskin_SOURCES = cdrskin/cdrskin.c cdrskin/cdrfifo.c cdrskin/cdrfifo.h cdrskin/cdrskin_timestamp.h
|
||||
## cdrskin_cdrskin_SOURCES = cdrskin/cdrskin.c cdrskin/cdrfifo.c cdrskin/cdrfifo.h cdrskin/cleanup.c cdrskin/cleanup.h cdrskin/cdrskin_timestamp.h
|
||||
##
|
||||
## Open questions: how to compute $timestamp and express -DX="$timestamp"
|
||||
##
|
||||
@ -159,7 +151,10 @@ doc/html: doc/doxygen.conf
|
||||
doc-upload: doc/html
|
||||
scp -r $</* $(webhost):$(webpath)
|
||||
|
||||
all: doc
|
||||
## ts B00729
|
||||
## Not by default any more.
|
||||
## It is unclear who is supposed to create file ./doc/doc.lock
|
||||
# all: doc
|
||||
|
||||
install-data-local:
|
||||
if [ -f ./doc/doc.lock ]; then \
|
||||
@ -174,13 +169,9 @@ uninstall-local:
|
||||
|
||||
# Indent source files
|
||||
indent_files = \
|
||||
$(libisofs_libisofs_la_SOURCES) \
|
||||
$(libburn_libburn_la_SOURCES) \
|
||||
$(test_libburner_SOURCES) \
|
||||
$(test_poll_SOURCES) \
|
||||
$(test_toc_SOURCES) \
|
||||
$(test_structest_SOURCES) \
|
||||
$(test_iso_SOURCES)
|
||||
$(test_structest_SOURCES)
|
||||
|
||||
|
||||
indent: $(indent_files)
|
||||
@ -196,15 +187,18 @@ indent: $(indent_files)
|
||||
|
||||
# Extra things
|
||||
nodist_pkgconfig_DATA = \
|
||||
libburn-1.pc \
|
||||
libisofs-1.pc
|
||||
libburn-1.pc
|
||||
|
||||
# http://www.nada.kth.se/cgi-bin/info?(automake.info)Man%20pages
|
||||
man_MANS = cdrskin/cdrskin.1
|
||||
|
||||
EXTRA_DIST = \
|
||||
libburn-1.pc.in \
|
||||
libisofs-1.pc.in \
|
||||
version.h.in \
|
||||
doc/comments \
|
||||
doc/doxygen.conf.in \
|
||||
doc/cookbook.txt \
|
||||
doc/mediainfo.txt \
|
||||
README \
|
||||
AUTHORS \
|
||||
CONTRIBUTORS \
|
||||
@ -212,12 +206,26 @@ EXTRA_DIST = \
|
||||
cdrskin/README \
|
||||
cdrskin/cdrecord_spy.sh \
|
||||
cdrskin/compile_cdrskin.sh \
|
||||
cdrskin/convert_man_to_html.sh \
|
||||
cdrskin/changelog.txt \
|
||||
cdrskin/cdrskin_eng.html \
|
||||
cdrskin/wiki_plain.txt \
|
||||
cdrskin/cleanup.h \
|
||||
cdrskin/cleanup.c \
|
||||
libburn/libburn.ver \
|
||||
libburn/os-dummy.h \
|
||||
libburn/os-freebsd.h \
|
||||
libburn/os-linux.h \
|
||||
libburn/os-libcdio.h \
|
||||
libburn/os-solaris.h \
|
||||
libburn/sg-dummy.c \
|
||||
libburn/sg-freebsd.c \
|
||||
libburn/sg-linux.c \
|
||||
COPYING
|
||||
libburn/sg-libcdio.c \
|
||||
libburn/sg-solaris.c \
|
||||
COPYING \
|
||||
NEWS \
|
||||
ChangeLog \
|
||||
INSTALL \
|
||||
$(man_MANS)
|
||||
|
||||
|
601
README
601
README
@ -1,97 +1,213 @@
|
||||
------------------------------------------------------------------------------
|
||||
libburn.pykix.org
|
||||
libburnia-project.org
|
||||
------------------------------------------------------------------------------
|
||||
This all is under GPL.
|
||||
(See GPL reference, our clarification and commitment at the end of this text)
|
||||
------------------------------------------------------------------------------
|
||||
libburn.pykix.org
|
||||
libburn-project.org
|
||||
By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
|
||||
Copyright (C) 2006 Mario Danic, Thomas Schmitt
|
||||
|
||||
Still containing parts of
|
||||
Libburn. By Derek Foreman <derek@signalmarketing.com> and
|
||||
Ben Jansens <xor@orodu.net>
|
||||
Copyright (C) 2006-2011 Mario Danic, Thomas Schmitt
|
||||
Still containing parts of Libburn. By Derek Foreman <derek@signalmarketing.com>
|
||||
and Ben Jansens <xor@orodu.net>
|
||||
Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
|
||||
These parts are to be replaced by own code of above libburn.pykix.org-copyright
|
||||
holders and then libburn.pykix.org is to be their sole copyright.
|
||||
This is done to achieve the right to issue the clarification and the
|
||||
commitment as written at the end of this text.
|
||||
The rights and merits of the Libburn-copyright holders Derek Foreman and
|
||||
Ben Jansens will be duely respected.
|
||||
|
||||
This libburn.pykix.org toplevel README (C) 2006 Thomas Schmitt
|
||||
http://files.libburnia-project.org/releases/libburn-1.1.0.pl01.tar.gz
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Build and Installation
|
||||
|
||||
Our build system is based on autotools. For preparing the build of a SVN
|
||||
snapshot you will need autotools of at least version 1.7.
|
||||
Check out from SVN by
|
||||
svn co http://libburn-svn.pykix.org/trunk libburn_pykix
|
||||
and apply autotools by
|
||||
./bootstrap
|
||||
From tarball
|
||||
|
||||
Alternatively you may unpack a release tarball for which you do not need
|
||||
autotools installed.
|
||||
Obtain libburn-1.1.0.pl01.tar.gz, take it to a directory of your choice and do:
|
||||
|
||||
To build libburn.pykix.org and its subprojects it should be sufficient to go
|
||||
into its toplevel directory (here: "libburn_pykix") and execute
|
||||
./configure
|
||||
tar xzf libburn-1.1.0.pl01.tar.gz
|
||||
cd libburn-1.1.0
|
||||
./configure --prefix=/usr
|
||||
make
|
||||
|
||||
To make the libraries accessible for running resp. developing applications
|
||||
To make libburn accessible for running resp. application development,
|
||||
and to install the cdrecord compatibility binary cdrskin, do
|
||||
(as Superuser):
|
||||
|
||||
make install
|
||||
|
||||
This procedure installs libburn.so.4 and cdrskin depending on it.
|
||||
For a standalone cdrskin binary, see cdrskin/README.
|
||||
|
||||
A behavioral conflict is known between any burn software and demons like hald
|
||||
which probe CD drives. This can spoil burn runs for CD-R or CD-RW.
|
||||
You may have to keep your hald away from the drive. See for example
|
||||
http://www.freebsd.org/gnome/docs/halfaq.html
|
||||
|
||||
|
||||
From SVN
|
||||
|
||||
Our build system is based on autotools. For preparing the build of a SVN
|
||||
snapshot you will need autotools of at least version 1.7.
|
||||
Do in a directory of your choice:
|
||||
|
||||
svn co http://svn.libburnia-project.org/libburn/trunk libburn-svn
|
||||
cd libburn-svn
|
||||
./bootstrap
|
||||
./configure --prefix=/usr
|
||||
make
|
||||
make install
|
||||
|
||||
Warning: The trunk might contain experimental features which might not
|
||||
persist until next release.
|
||||
|
||||
|
||||
Special ./configure options
|
||||
|
||||
make install on GNU/Linux will try to run program ldconfig with the library
|
||||
installation directory as only argument. Failure to do so will not abort
|
||||
installation. One may disable ldconfig by ./configure option:
|
||||
--disable-ldconfig-at-install
|
||||
|
||||
In some situations Linux may deliver a better write performance to drives if
|
||||
the track input is read with O_DIRECT (see man 2 open). The API call
|
||||
burn_os_open_track_src() and the input readers of cdrskin and libburn fifo
|
||||
can be told to use this peculiar read mode by:
|
||||
--enable-track-src-odirect
|
||||
|
||||
But often libburn call burn_write_opts_set_dvd_obs(opts, 64*1024) will yield
|
||||
even better performance in such a situation. 64k can be made default at
|
||||
configure time by:
|
||||
--enable-dvd-obs-64k
|
||||
This may be combined with above --enable-track-src-odirect .
|
||||
|
||||
Alternatively the transport of SCSI commands can be done via libcdio-0.83.
|
||||
You may install it and re-run libburn's ./configure with option
|
||||
--enable-libcdio
|
||||
|
||||
By use of a version script, the libburn.so library exposes no other function
|
||||
names but those of the API definition in libburn/libburn.h.
|
||||
If -Wl,--version-script=... makes problems with the local compiler, then
|
||||
disable this encapsulation feature by
|
||||
--disable-versioned-libs
|
||||
|
||||
Make sure to re-compile all source files after running ./configure
|
||||
make clean ; make
|
||||
make install
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Overview of libburn.pykix.org
|
||||
An important part of the project, libisofs, is hosted in a bzr repository at
|
||||
launchpad.net :
|
||||
bzr branch lp:libisofs
|
||||
|
||||
libburn.pykix.org is an open-source library for reading, mastering and writing
|
||||
optical discs. For now this means only CD-R and CD-RW.
|
||||
Another part the project, libisoburn, is hosted in the libburnia SVN, too:
|
||||
svn co http://svn.libburnia-project.org/libisoburn/trunk libisoburn
|
||||
|
||||
See README files there.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
|
||||
Overview of libburnia-project.org
|
||||
|
||||
libburnia-project.org is an open-source software project for reading, mastering
|
||||
and writing optical discs.
|
||||
For now this means CD media, all DVD media except DVD-R DL, all BD media.
|
||||
|
||||
The project comprises of several more or less interdependent parts which
|
||||
together strive to be a usable foundation for application development.
|
||||
These are libraries, language bindings, and middleware binaries which emulate
|
||||
classical (and valuable) Linux tools.
|
||||
Currently it is supported on GNU/Linux with kernels >= 2.4,
|
||||
on FreeBSD with ATAPI/CAM enabled in the kernel (see man atapicam),
|
||||
and on OpenSolaris (tested with kernel 5.11).
|
||||
On other X/Open compliant systems there will only be pseudo drives, but no
|
||||
direct MMC operation on real CD/DVD/BD drives.
|
||||
|
||||
Our scope is currently Linux 2.4 and 2.6 and we will have a hard time to widen
|
||||
this for now, because of our history. The project could need advise from or
|
||||
membership of skilled kernel people and people who know how to talk CD/DVD
|
||||
drives into doing things.
|
||||
For full ports to other systems we would need : login on a development machine
|
||||
resp. a live OS on CD or DVD, advise from a system person about the equivalent
|
||||
of Linux sg or FreeBSD CAM, volunteers for testing of realistic use cases.
|
||||
|
||||
We do have a workable code base for burning data CDs, though. The burn API is
|
||||
quite comprehensively documented and can be used to build a presentable
|
||||
application.
|
||||
We do have a functional binary which emulates parts of cdrecord in order to
|
||||
prove that usability, and in order to allow you to explore libburn's scope
|
||||
by help of existing cdrecord frontends.
|
||||
We have a well tested code base for burning data and audio CDs, DVDs and BDs.
|
||||
The burn API is quite comprehensively documented and can be used to build a
|
||||
presentable application.
|
||||
We have a functional application which emulates the core use cases of cdrecord
|
||||
in order to prove that usability, and in order to allow you to explore
|
||||
libburn's scope by help of existing cdrecord frontends.
|
||||
|
||||
ISO 9660 filesystems with Rock Ridge and Joliet extensions can be created
|
||||
and manipulated quite freely. This capability together with our burn capability
|
||||
makes possible a single binary application which covers all steps of image
|
||||
composition, updating and writing. Quite unique in the Linux world.
|
||||
|
||||
The project components (list subject to growth, hopefully):
|
||||
|
||||
- libburn is the library by which preformatted data get onto optical media.
|
||||
It uses either /dev/sgN (e.g. on kernel 2.4 with ide-scsi) or
|
||||
/dev/hdX (e.g. on kernel 2.6).
|
||||
libburn is the foundation of our cdrecord emulation.
|
||||
/dev/srM or /dev/hdX (e.g. on kernel 2.6).
|
||||
libburn is the foundation of our cdrecord emulation. Its code is
|
||||
independent of cdrecord. Its DVD capabilities are learned from
|
||||
studying the code of dvd+rw-tools and MMC-5 specs. No code but only
|
||||
the pure SCSI knowledge has been taken from dvd+rw-tools, though.
|
||||
|
||||
- libisofs is the library to pack up hard disk files and directories into a
|
||||
ISO 9660 disk image. This may then be brought to CD via libburn.
|
||||
libisofs is to be the foundation of our upcoming mkisofs emulation.
|
||||
An own ISO 9660 extension stores ACLs, xattr, and MD5 of file
|
||||
content.
|
||||
|
||||
- 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.
|
||||
It also contains the methods of command oriented application
|
||||
xorriso and offers them via a C language API.
|
||||
|
||||
- cdrskin is a limited cdrecord compatibility wrapper for libburn.
|
||||
Cdrecord is a powerful GPL'ed burn program included in Joerg
|
||||
cdrecord is a powerful GPL'ed burn program included in Joerg
|
||||
Schilling's cdrtools. cdrskin strives to be a second source for
|
||||
the services traditionally provided by cdrecord.
|
||||
the services traditionally provided by cdrecord. Additionally it
|
||||
provides libburn's DVD capabilities, where only -sao is compatible
|
||||
with cdrecord.
|
||||
cdrskin does not contain any bytes copied from cdrecord's sources.
|
||||
Many bytes have been copied from the message output of cdrecord
|
||||
runs, though.
|
||||
See cdrskin/README for more.
|
||||
|
||||
- test is a collection of application gestures and examples given by the
|
||||
authors of the library features. The main API example for libburn
|
||||
is test/libburner.c .
|
||||
- xorriso is an application of all three libraries which creates, loads,
|
||||
manipulates and writes ISO 9660 filesystem images with
|
||||
Rock Ridge extensions. Manipulation is not only adding or
|
||||
overwriting of files but also deleting, renaming, attribute
|
||||
changing, incremental backups, activating boot images, and
|
||||
extracting of files from ISO images to disk. There is also a
|
||||
sparse emulation of cdrecord and a more laborate one of mkisofs.
|
||||
All features of xorriso are also available via a C language API
|
||||
of libisoburn.
|
||||
See xorriso/README for more.
|
||||
|
||||
- "test" is a collection of application gestures and examples given by the
|
||||
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).
|
||||
|
||||
Applications must use 64 bit off_t. E.g. by defining
|
||||
#define _LARGEFILE_SOURCE
|
||||
#define _FILE_OFFSET_BITS 64
|
||||
or take special precautions to interface with the libraries by 64 bit integers
|
||||
where the .h files prescribe off_t. To reduce libburn's off_t size to 32 bit
|
||||
will keep it from processing tracks of more than 2 GB size.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
@ -114,13 +230,13 @@ Project history as far as known to me:
|
||||
It has meanwhile moved to use vanilla libburn.pykix.org , though.
|
||||
Version 0.1.4 constitutes the first release of this kind.
|
||||
|
||||
- In Juli 2006 our team mate Mario Danic announced a revival of libburn
|
||||
- In July 2006 our team mate Mario Danic announced a revival of libburn
|
||||
which by about nearly everybody else was perceived as unfriendly fork.
|
||||
Derek Foreman four days later posted a message which expressed his
|
||||
discontent.
|
||||
The situation first caused me to publically regret it and then - after i
|
||||
got the opportunity to move in with cdrskin - gave me true reason to
|
||||
personally apologize to Derek Foreman, Ben Jansens and the contibutors at
|
||||
personally apologize to Derek Foreman, Ben Jansens and the contributors at
|
||||
icculus.org/burn. Posted to both projects:
|
||||
http://lists.freedesktop.org/archives/libburn/2006-August/000446.html
|
||||
http://mailman-mail1.webfaction.com/pipermail/libburn-hackers/2006-August/000024.html
|
||||
@ -158,13 +274,367 @@ Project history as far as known to me:
|
||||
This version of cdrskin is much more cdrecord compatible in repect
|
||||
to drive addressing and audio features.
|
||||
|
||||
- 30th October 2006 release of cdrskin-0.2.4 .
|
||||
|
||||
- 13th November 2006 splitting releases of libburn+cdrskin from libisofs.
|
||||
|
||||
- 24th November 2006 release of libburn-0.2.6 and cdrskin-0.2.6 . cdrskin has
|
||||
become suitable for unaware frontends as long as they perform only the core
|
||||
of cdrecord use cases (including open-ended input streams, audio, and
|
||||
multi-session).
|
||||
|
||||
- 28th November 2006 the umbrella project which encloses both, libisofs and
|
||||
libburn, is now called libburnia. For the origin of this name, see
|
||||
http://en.wikipedia.org/wiki/Liburnians .
|
||||
|
||||
- 16th January 2007 release of libburn-0.3.0 and cdrskin-0.3.0 . Now the scope
|
||||
is widened to a first class of DVD media: overwriteable single layer types
|
||||
DVD-RAM, DVD+RW, DVD-RW. This is not a cdrecord emulation but rather inspired
|
||||
by dvd+rw-tools' "poor man" writing facility for this class of media.
|
||||
Taking a bow towards Andy Polyakov.
|
||||
|
||||
- 11th February 2007 version 0.3.2 covers sequential DVD-RW and DVD-R with
|
||||
multi-session and with DAO.
|
||||
|
||||
- 12th March 2007 version 0.3.4 supports DVD+R and thus covers all single layer
|
||||
DVD media. Code for double layer DVD+/-R is implemented but awaits a tester
|
||||
yet.
|
||||
|
||||
- 23th April 2007 version 0.3.6 follows the unanimous opinion of Linux kernel
|
||||
people that one should not use /dev/sg on kernel 2.6.
|
||||
|
||||
- 31st July 2007 version 0.3.8 marks the first anniversary of libburn revival.
|
||||
We look back on improved stability, a substantially extended list of media
|
||||
and write modes, and better protection against typical user mishaps.
|
||||
|
||||
- 24th October 2007 version 0.4.0 is the foundation of new library libisoburn
|
||||
and an upcomming integrated application for manipulating and writing
|
||||
ISO 9660 + Rock Ridge images. cdrskin-0.4.0 got capabilities like growisofs
|
||||
by these enhancements: growing of overwriteable media and disk files.
|
||||
Taking again a bow towards Andy Polyakov.
|
||||
|
||||
- 26th Januar 2008 version 0.4.2 rectifies the version numbering so that we
|
||||
reliably release libburn.so.4 as should have been done since libburn-0.3.2.
|
||||
cdrskin now is by default linked dynamically and does a runtime check
|
||||
to ensure not to be started with a libburn which is older than itself.
|
||||
|
||||
- 3rd Feb 2008 libisofs-0.2.x (.so.5) has been deprecated.
|
||||
|
||||
- 14th Feb 2008 libisofs-0.6.2 permanently replaces the old libisofs-0.2.x.
|
||||
It is the first release of new libisofs.so.6 which will guarantee future
|
||||
API/ABI compatibility for its whole feature set.
|
||||
|
||||
- 15th Feb 2008 libisoburn-0.1.0 (.so.1) coordinates libisofs and libburn for
|
||||
the purpose of ISO image reading and writing. It emulates multi-session on
|
||||
overwriteable media. Application xorriso makes use of all three libraries.
|
||||
|
||||
- 8th Apr 2008 libburn-0.4.4 has proven to be capable of burning to DVD+R/DL
|
||||
and read performance on disk file pseudo-drives has been improved.
|
||||
|
||||
- 27th Apr 2008 libisofs-0.6.4 can now read data file content from images
|
||||
and can map pieces of disk files onto image files. Image directory iteration
|
||||
has been enhanced. Input data streams and extended information have been
|
||||
exposed in the API to allow future development.
|
||||
|
||||
- 29th Apr 2008 libisoburn-0.1.4 was made more efficient with reading of
|
||||
image tree nodes. It now depends on libisofs-0.6.4 and libburn-0.4.4.
|
||||
xorriso makes use of new libisofs features by performing incremental
|
||||
updates of directory trees and by cutting oversized data files into
|
||||
pieces. A primitive single session emulation of cdrecord and mkisofs is
|
||||
provided.
|
||||
|
||||
- 10th May 2008 libburn-0.4.6 supports formatting and writing of BD-RE,
|
||||
full nominal speed for DVD-RAM and BD-RE. cdrskin has a unified blank
|
||||
type with automatic media state recognition.
|
||||
|
||||
- 17th May 2008 an old bug with DVD-RAM and now with BD-RE is fixed by
|
||||
libburn-0.4.8 to allow libisoburn emulation of multisession on those media.
|
||||
|
||||
- 19th May 2008 libisoburn-0.1.6 brings better table-of-content emulation
|
||||
on overwriteble media and disk files.
|
||||
|
||||
- 1st Jun 2008 libisofs-0.6.6 fixes some problems around device files.
|
||||
|
||||
- 3rd Jun 2008 libisoburn-0.1.8 fixes a bug with overwriteable media.
|
||||
|
||||
- 23rd Jun 2008 libisoburn-0.2.0 introduces extraction of files from
|
||||
ISO images.
|
||||
|
||||
- 16th Jul 2008 libburn-0.5.0 handles systems with no /dev/sr* but only
|
||||
/dev/scd*.
|
||||
|
||||
- 19th Jul 2008 libisoburn/xorriso-0.2.2 can do multi-session in mkisofs
|
||||
and cdrecord style. xorriso now can serve underneath growisofs.
|
||||
|
||||
- 20th Aug 2008 libburn-0.5.2 revokes the necessity that a drive must be
|
||||
enumerable in order to be adressable. Enumeration is enhanced by examining
|
||||
/proc/sys/dev/cdrom/info.
|
||||
|
||||
- 24th Aug 2008 libisoburn/xorriso-0.2.4 introduces a media readability check
|
||||
with data retrieval option.
|
||||
|
||||
- 18th Sep 2008 libisofs-0.6.8 supports ISO 9660 Level 3 which allows very
|
||||
large data files in the image.
|
||||
|
||||
- 20th Sep 2008 libisoburn/xorriso-0.2.6 takes into respect the new Level 3
|
||||
capabilities of libisofs.
|
||||
|
||||
- 6th Oct 2008 libburn-0.5.4 adjusts the changes of 0.5.2 to the needs of
|
||||
Linux kernel 2.4 and introduces human readable SCSI error messages.
|
||||
|
||||
- 6th Oct 2008 libisofs-0.6.10 fixes two bugs which prevented adding and
|
||||
manipulation of ISOLINUX boot images.
|
||||
|
||||
- 15th Oct 2008 libisoburn/xorriso-0.2.8 can activate and maintain an
|
||||
ISOLINUX boot image by an EL Torito boot record.
|
||||
|
||||
- 12th Nov 2008 libburn-0.5.6 fixes usage of freed memory by the fifo thread
|
||||
of an aborted burn run.
|
||||
|
||||
- 26th Nov 2008 libisofs-0.6.12 can produce a ISOLINUX isohybrid MBR on the fly
|
||||
and allows to produce ISO images which resemble old mkisofs images.
|
||||
|
||||
- 2nd Dec 2008 libisoburn-0.3.0. xorriso now is ready for exotic character
|
||||
sets, for legacy FreeBSD systems which expect an outdated Rock Ridge
|
||||
signature, and for producing ISO images with MBR which boot from hard disk
|
||||
or USB stick. Three minor bugs were fixed.
|
||||
|
||||
- 7th Dec 2008 libburn-0.5.8 prevents a SIGSEGV with wierd CD table-of-content
|
||||
and improves BD-RE formatting.
|
||||
|
||||
- 9th Dec 2008 Our project received a donation from Thomas Weber.
|
||||
|
||||
- 2nd Jan 2009 libburn-0.6.0 allows to format BD-R and to write to either
|
||||
formatted or unformatted BD-R.
|
||||
|
||||
- 6th Jan 2009 libisoburn-0.3.2. xorriso can produce and execute commands for
|
||||
mounting older sessions from all kinds of media. Pseudo-drives outside the
|
||||
/dev/ tree can be addressed without prefix "stdio:".
|
||||
|
||||
- 20th Feb 2009 libburn-0.6.2 source release now compiles out of the box
|
||||
on FreeBSD.
|
||||
|
||||
- 28 Feb 2009 libisofs-0.6.14 can record ACLs and Extended Attributes xattr
|
||||
in its ISO images.
|
||||
|
||||
- 01 Mar 2009 libisoburn-0.3.4. xorriso makes use of the ACL and xattr
|
||||
capabilities provided by libisofs for xorriso backup features.
|
||||
|
||||
- 11 Mar 2009 libisofs-0.6.16 of libisofs fixes two bugs which on Solaris
|
||||
prevented to navigate the ISO images by ".." and to recognize the Rock Ridge
|
||||
extensions of ISO images. The ban to build libisofs on operating systems
|
||||
other than Linux and FreeBSD has been lifted.
|
||||
|
||||
- 13 Mar 2009 libburn-0.6.4 got a dummy adapter for SCSI/MMC command transport.
|
||||
It will show no drives and thus libburn will only be able to perform
|
||||
operations on "stdio:" pseudo drives. Nevertheless this allowed to lift the
|
||||
ban to build libburn on operating systems other than Linux and FreeBSD.
|
||||
|
||||
- 16 Mar 2009 libisoburn-0.3.6: xorriso uses RRIP version 1.10 as default
|
||||
in order to be mountable where mkisofs images are mountable.
|
||||
|
||||
- 17 Apr 2009 libisofs-0.6.18 introduces content filtering of data files.
|
||||
Built-in filters allow compression to formats gzip and zisofs. External
|
||||
filter processes allow arbitrary data conversions like encryption.
|
||||
|
||||
- 19 Apr 2009 libisoburn-0.3.8 makes use of the new libisofs capability to
|
||||
perform content filtering of data files.
|
||||
|
||||
- 08 May 2009 libburn-0.6.6 fixes a bug with aborting on broken output pipe
|
||||
and a bug with device scan on FreeBSD.
|
||||
|
||||
- 31 May 2009 libisofs-0.6.20 can record hard link relations in ISO images
|
||||
and offers support with restoring them to disk. Current Linux kernels will
|
||||
mount images with such hard links but will attribute a unique inode number
|
||||
to each file.
|
||||
|
||||
- 28 Jun 2009 libisoburn-0.4.0: xorriso can record and restore hard link
|
||||
relations of files. Performance of data reading has been improved. Option
|
||||
-find now supports logical operators with its tests.
|
||||
|
||||
- 14 Jul 2009 libburn-0.6.8 fixes bugs and shortcommings with old MMC-1 drives
|
||||
and with large SCSI bus numbers as handed out by Linux for USB drives.
|
||||
|
||||
- 20 Jul 2009 libisoburn-0.4.0.pl01 fixes a regression in xorriso which caused
|
||||
data loss in older sessions if xorriso was used underneath growisofs.
|
||||
Affected are releases since libisoburn-0.3.2 in january 2009.
|
||||
|
||||
- 25 Aug 2009 libisofs-0.6.22 can record MD5 checksums for the whole session
|
||||
and for each single data file. Checksum tags allow to verify superblock and
|
||||
directory tree before importing them.
|
||||
|
||||
- 27 Aug 2009 libburn-0.7.0 allows to calm down a drive and to inquire its
|
||||
supported profiles. It works around some pitfalls with U3 enhanced memory
|
||||
sticks which emulate a CD-ROM.
|
||||
|
||||
- 27 Aug 2009 libisoburn-0.4.0.pl00 can record MD5 checksums by which one may
|
||||
verify the session or single data files in the image. When comparing image
|
||||
files with files in the local filesystem, the MD5 sums avoid the need for
|
||||
reading file content from the image.
|
||||
|
||||
- 22 Sep 2009 libisoburn-0.4.0.pl01 fixes a bug in xorriso option -cut_out.
|
||||
|
||||
- 08 Oct 2009 libisofs-0.6.24 fixes a bug which could cause the loss of blanks
|
||||
in file names when a new session got added to an ISO image. With names
|
||||
shorter than 251 characters this happened only to trailing blanks.
|
||||
|
||||
- 08 Oct 2009 libisoburn-0.4.0.pl02 fixes bugs with xorriso option -for_backup,
|
||||
with xorrisofs -help, and with xorrecord -help.
|
||||
|
||||
- 12 Oct 2009 libburn-0.7.2 fixes a bug with CD TAO multi-track dummy sessions.
|
||||
It can retrieve media product info and can process track input which was
|
||||
prepared for CD-ROM XA Mode 2 Form 1. cdrskin now performs option -minfo.
|
||||
|
||||
- 28 Oct 2009 libisoburn-0.4.4 fixes a bug with cdrecord emulation and
|
||||
introduces new information options about media type and ISO image id strings.
|
||||
On Linux it helps with mounting two sessions of the same media
|
||||
simultaneously.
|
||||
|
||||
- 12 Nov 2009 libburn-0.7.2.pl01 works around problems with Pioneer DVR-216D.
|
||||
DVD-R runs made the drive stuck. Ejecting the tray did not work properly.
|
||||
|
||||
- 06 Dec 2009 libburn-0.7.4 works around problems with newer DVD burners,
|
||||
provides throughput enhancements with hampered busses on Linux, and new
|
||||
API calls to log SCSI commands and to control the libburn fifo.
|
||||
|
||||
- 09 Dec 2009 libisoburn-0.4.6 allows performance tuning of output to DVD
|
||||
drives or disk files.
|
||||
|
||||
- 26 Dec 2009 libburn-0.7.4.pl01 fixes the release tarball which was lacking
|
||||
the files of the generic system adapter for X/Open.
|
||||
|
||||
- 29 Dec 2009 Our project received a donation for purchasing a fine small
|
||||
computer which shall serve as OS farm for development and support.
|
||||
|
||||
- 20 Jan 2010 Version 0.6.26 of libisofs fixes minor bugs and shall enhance
|
||||
portability.
|
||||
|
||||
- 22 Jan 2010 libburn-0.7.6 has an improved system adapter for FreeBSD,
|
||||
fixes bugs about the generic X/Open system adapter, and allows to use
|
||||
libcdio >= 0.83 as SCSI transport facility.
|
||||
|
||||
- 10 Feb 2010 libisofs-0.6.28 fixes a regression about bootable images which
|
||||
was introduced by version 0.6.22 in August 2009.
|
||||
|
||||
- 23 Feb 2010 libisoburn-0.5.0 marks the transition of the xorriso standalone
|
||||
version to an official GNU project. The name changed to "GNU xorriso" and its
|
||||
license is now GPLv3+.
|
||||
The licenses of libburnia libraries and applications are not affected by
|
||||
this change.
|
||||
|
||||
- 10 Mar 2010 libburn-0.7.8 fixes bugs and improves the built-in abort handler
|
||||
on FreeBSD.
|
||||
|
||||
- 30 Mar 2010 Release 0.5.2 of libisoburn provides xorriso documentation in
|
||||
GNU Texinfo format with embedded extra data to derive a full man page.
|
||||
|
||||
- 09 Apr 2010 libburn-0.8.0 now works with ahci driver on FreeBSD 8-STABLE.
|
||||
|
||||
- 03 May 2010 Version 0.6.32 of libisofs is able to create ISO images with
|
||||
multiple boot images. All boot catalog parameters described in El-Torito
|
||||
specs can be set and inquired. This allows to use GRUB boot images for EFI.
|
||||
|
||||
- 04 May 2010 Release 0.5.6.pl00 of libisoburn makes use of the new libisofs
|
||||
capabilities about boot images.
|
||||
|
||||
- 11 Jun 2010 libburn-0.8.2 now works on Solaris.
|
||||
|
||||
- 14 Jun 2010 By release 0.5.8.pl00 of libisoburn, xorriso becomes a public C
|
||||
language API of libisoburn. The emulations of mkisofs and cdrecord have
|
||||
been enhanced.
|
||||
|
||||
- Tue Jun 29 2010 Version 0.6.34 of libisofs provides new features about
|
||||
hiding file names from directory trees.
|
||||
|
||||
- Wed Jun 30 2010 libburn-0.8.4 removes some restrictions on operating
|
||||
systems other than Linux and FreeBSD.
|
||||
|
||||
- Fri Jul 02 2010 Release 0.6.0.pl00 of libisoburn adds more options to the
|
||||
mkisofs emulation of xorriso. It also fixes minor bugs and shortcommings.
|
||||
|
||||
- Wed Sep 15 2010 Version 0.6.36 of libisofs can produce ISO images which
|
||||
bear a partiton 1 with non-zero start address. They can be mounted from
|
||||
USB stick via the main device file (e.g. /dev/sdb) as well as via the
|
||||
partition device file (e.g. /dev/sdb1).
|
||||
|
||||
- Fri Sep 17 2010 libburn-0.8.6 lifts the test reservation on DVD-R DL media.
|
||||
|
||||
- Sat Sep 18 2010 Release 0.6.2.pl00 of libisoburn introduces a partition
|
||||
with non-zero offset for ISO 9660 images on USB sticks, improves mkisofs
|
||||
emulation, and fixes a regression which existed since version 0.4.2.
|
||||
|
||||
- Wed Oct 20 2010 libburn-0.8.8 can report the used amount of BD spare blocks.
|
||||
|
||||
- Sat Oct 23 2010 Version 0.6.38 of libisofs can use libjte to produce jigdo
|
||||
files along with the ISO image. Further filesystem images may be appended
|
||||
as MBR partitions 1 to 4. The capability was added to produce boot blocks
|
||||
for computers with MIPS CPU.
|
||||
|
||||
- Tue Oct 26 2010 Release 0.6.4.pl00 of libisoburn and xorriso makes use of
|
||||
the new libisofs capabilities.
|
||||
|
||||
- Wed Dec 08 2010 libburn-0.9.0 fixes a regression with SCSI command logging.
|
||||
|
||||
- Fri Dec 10 2010 Version 0.6.40 of libisofs makes the prediction of the
|
||||
emerging image size less expensive and is able to make images bootable
|
||||
for SUN SPARC systems.
|
||||
|
||||
- Sun Dec 12 2010 Release 0.6.6.pl00 of libisoburn and xorriso can read ISO
|
||||
images which were copied to a different start address than they were prepared
|
||||
for.
|
||||
|
||||
- Mon Jan 17 2011 we go for release 1.0.0. This does not indicate a
|
||||
technological overhaul but shall emphasize the maturity of the software.
|
||||
libisofs-1.0.0 fixes a bug about the length of ECMA-119 directory names and
|
||||
is ready to allow untranslated ECMA-119 names (violating the specs).
|
||||
libburn-1.0.0.pl00 allows umask to create stdio-drive files with
|
||||
rw-permissions for all. cdrskin now refuses to burn if the foreseeable size
|
||||
exceeds media capacity
|
||||
libisoburn-1.0.0.pl00 allows to create an ISO 9660:1999 directory tree,
|
||||
improved the emulation fidelity of command -as mkisofs, lowered the default
|
||||
abort threshold for xorriso batch mode, and increased that threshold for
|
||||
xorriso dialog mode.
|
||||
|
||||
- Wed Feb 23 2011 release 1.0.2:
|
||||
libisofs fixes several bugs and introduces the capability to copy files
|
||||
inside the ISO filesystem.
|
||||
libburn removed a compilation obstacle on Solaris 9 and improved recognition
|
||||
of stdio pseudo-drives.
|
||||
libisoburn and xorriso fix bugs and make use of the new libisofs capability.
|
||||
xorriso improves its mkisofs emulation.
|
||||
|
||||
- Thu Mar 10 2011 release 1.0.4:
|
||||
Several bugs were fixed in the libraries and in the mkisofs emulation of
|
||||
xorriso. This emulation xorrisofs has now an own man page and info document.
|
||||
|
||||
- Sat Apr 09 2011 release 1.0.6:
|
||||
libburn refined its representation of emulated drives. The size alignment
|
||||
of DVD DAO is now 2 kB rather than 32 kB. libisofs produces Joliet names of
|
||||
up to 103 characters. xorriso fixes two bugs and makes use of the library
|
||||
improvements.
|
||||
|
||||
- Thu Apr 14 2011 release libisoburn-1.0.8:
|
||||
A bug in the mkisofs emulation of xorriso could cause options to be ignored.
|
||||
The problem was freshly introduced with libisoburn-1.0.6.
|
||||
|
||||
- Fri May 13 2011 release libisofs-1.0.8:
|
||||
Fixes a few rarely occurring bugs that have been found during the last month.
|
||||
|
||||
- Sat Jun 18 2011 release 1.1.0:
|
||||
The consumption of stack memory was reduced. Statical program analysis found
|
||||
some rarely occuring memory leaks. Several small bugs were fixed.
|
||||
The suffix .plXY was dropped from tarball names of libburn and libisoburn.
|
||||
|
||||
- Mon Jun 20 2011 patch release libburn-1.1.0.pl01:
|
||||
libburn-1.1.0 compiled only on Linux, FreeBSD, and Solaris, but not on
|
||||
other X/Open compliant systems.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
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 or later
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
@ -177,21 +647,21 @@ Project history as far as known to me:
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Clarification in my name and in the name of Mario Danic, upcoming copyright
|
||||
holders on toplevel of libburn. To be fully in effect after the remaining other
|
||||
copyrighted code has been replaced by ours and by copyright-free contributions
|
||||
of our friends:
|
||||
holders on toplevel of libburnia. To be fully in effect after the remaining
|
||||
other copyrighted code has been replaced by ours and by copyright-free
|
||||
contributions of our friends:
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
We, the copyright holders, agree on the interpretation that
|
||||
dynamical linking of our libraries constitutes "use of" and
|
||||
not "derivation from" our work in the sense of GPL, provided
|
||||
those libraries are compiled from our unaltered code.
|
||||
We, the copyright holders, agree on the interpretation that dynamical linking
|
||||
of our libraries constitutes "use of" and not "derivation from" our work in
|
||||
the sense of GPL, provided those libraries are compiled from our unaltered
|
||||
code or from altered code published under GPL.
|
||||
|
||||
Thus you may link our libraries dynamically with applications
|
||||
which are not under GPL. You may distribute our libraries and
|
||||
application tools in binary form, if you fulfill the usual
|
||||
condition of GPL to offer a copy of the source code -altered
|
||||
or unaltered- under GPL.
|
||||
So we will not raise legal protest if you link our libraries dynamically with
|
||||
applications which are not under GPL, or if you distribute our libraries
|
||||
and application tools in binary form, as long as you fulfill the usual
|
||||
condition of GPL to offer a copy of their source code -altered or unaltered-
|
||||
under GPL.
|
||||
|
||||
We ask you politely to use our work in open source spirit
|
||||
and with the due reference to the entire open source community.
|
||||
@ -208,4 +678,5 @@ means to qualify for GPL.
|
||||
For now we are firmly committed to maintain one single license: GPL.
|
||||
|
||||
signed: Mario Danic, Thomas Schmitt
|
||||
Agreement joined later by: Vreixo Formoso
|
||||
|
||||
|
97
acinclude.m4
97
acinclude.m4
@ -1,22 +1,111 @@
|
||||
AC_DEFUN([LIBBURNIA_SET_FLAGS],
|
||||
[
|
||||
case $target_os in
|
||||
freebsd*)
|
||||
LDFLAGS="$LDFLAGS -L/usr/local/lib"
|
||||
CPPFLAGS="$CPPFLAGS -I/usr/local/include"
|
||||
;;
|
||||
esac
|
||||
])
|
||||
|
||||
|
||||
AC_DEFUN([TARGET_SHIZZLE],
|
||||
[
|
||||
ARCH=""
|
||||
LIBBURNIA_PKGCONFDIR="$libdir"/pkgconfig
|
||||
|
||||
AC_MSG_CHECKING([target operating system])
|
||||
|
||||
case $target in
|
||||
*-*-linux*)
|
||||
LIBBURNIA_LDCONFIG_CMD="echo 'No ldconfig run performed. If needed, configure manually for:'"
|
||||
|
||||
case $target_os in
|
||||
linux*)
|
||||
ARCH=linux
|
||||
LIBBURN_ARCH_LIBS=
|
||||
LIBBURNIA_LDCONFIG_CMD=ldconfig
|
||||
;;
|
||||
*-*-freebsd*)
|
||||
freebsd*)
|
||||
ARCH=freebsd
|
||||
LIBBURN_ARCH_LIBS=-lcam
|
||||
LIBBURNIA_PKGCONFDIR=$(echo "$libdir" | sed 's/\/lib$/\/libdata/')/pkgconfig
|
||||
;;
|
||||
kfreebsd*-gnu)
|
||||
ARCH=freebsd
|
||||
LIBBURN_ARCH_LIBS=-lcam
|
||||
;;
|
||||
*)
|
||||
AC_ERROR([You are attempting to compile for an unsupported platform])
|
||||
ARCH=
|
||||
LIBBURN_ARCH_LIBS=
|
||||
# AC_ERROR([You are attempting to compile for an unsupported platform])
|
||||
;;
|
||||
esac
|
||||
|
||||
AC_MSG_RESULT([$ARCH])
|
||||
])
|
||||
|
||||
|
||||
dnl LIBBURN_ASSERT_VERS_LIBS is by Thomas Schmitt, libburnia project
|
||||
dnl It tests whether -Wl,--version-script=... works with the compiler
|
||||
AC_DEFUN([LIBBURN_ASSERT_VERS_LIBS],
|
||||
[
|
||||
libburnia_save_LDFLAGS="$LDFLAGS"
|
||||
LDFLAGS="$LDFLAGS -Wl,--version-script=libburn/libburn.ver"
|
||||
AC_TRY_LINK([#include <stdio.h>], [printf("Hello\n");],
|
||||
[vers_libs_test="yes"], [vers_libs_test="no"])
|
||||
if test x$vers_libs_test = xno
|
||||
then
|
||||
LDFLAGS="$libburnia_save_LDFLAGS"
|
||||
fi
|
||||
])
|
||||
|
||||
|
||||
dnl LIBBURNIA_SET_PKGCONFIG determines the install directory for the *.pc file.
|
||||
dnl Important: Must be performed _after_ TARGET_SHIZZLE
|
||||
dnl
|
||||
AC_DEFUN([LIBBURNIA_SET_PKGCONFIG],
|
||||
[
|
||||
### for testing --enable-libdir-pkgconfig on Linux
|
||||
### LIBBURNIA_PKGCONFDIR="$libdir"data/pkgconfig
|
||||
|
||||
if test "x$LIBBURNIA_PKGCONFDIR" = "x$libdir"/pkgconfig
|
||||
then
|
||||
dummy=dummy
|
||||
else
|
||||
AC_ARG_ENABLE(libdir-pkgconfig,
|
||||
[ --enable-libdir-pkgconfig Install to $libdir/pkgconfig on any OS, default=no],
|
||||
, enable_libdir_pkgconfig="no")
|
||||
AC_MSG_CHECKING([for --enable-libdir-pkgconfig])
|
||||
if test "x$enable_libdir_pkgconfig" = xyes
|
||||
then
|
||||
LIBBURNIA_PKGCONFDIR="$libdir"/pkgconfig
|
||||
fi
|
||||
AC_MSG_RESULT([$enable_libdir_pkgconfig])
|
||||
fi
|
||||
|
||||
libburnia_pkgconfig_override="no"
|
||||
AC_ARG_ENABLE(pkgconfig-path,
|
||||
[ --enable-pkgconfig-path=DIR Absolute path of directory for libisofs-*.pc],
|
||||
libburnia_pkgconfig_override="yes" , enable_pkgconfig_path="none")
|
||||
AC_MSG_CHECKING([for overridden pkgconfig directory path])
|
||||
if test "x$enable_pkgconfig_path" = xno
|
||||
then
|
||||
libburnia_pkgconfig_override="no"
|
||||
fi
|
||||
if test "x$enable_pkgconfig_path" = x -o "x$enable_pkgconfig_path" = xyes
|
||||
then
|
||||
libburnia_pkgconfig_override="invalid argument"
|
||||
fi
|
||||
if test "x$libburnia_pkgconfig_override" = xyes
|
||||
then
|
||||
LIBBURNIA_PKGCONFDIR="$enable_pkgconfig_path"
|
||||
AC_MSG_RESULT([$LIBBURNIA_PKGCONFDIR])
|
||||
else
|
||||
AC_MSG_RESULT([$libburnia_pkgconfig_override])
|
||||
fi
|
||||
AC_SUBST(LIBBURNIA_PKGCONFDIR)
|
||||
|
||||
dnl For debugging only
|
||||
### AC_MSG_RESULT([LIBBURNIA_PKGCONFDIR = $LIBBURNIA_PKGCONFDIR])
|
||||
|
||||
])
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
#!/bin/sh -x
|
||||
|
||||
aclocal
|
||||
aclocal -I .
|
||||
libtoolize --copy --force
|
||||
autoconf
|
||||
|
||||
|
625
cdrskin/README
625
cdrskin/README
@ -1,101 +1,69 @@
|
||||
------------------------------------------------------------------------------
|
||||
libburn.pykix.org scdbackup.sourceforge.net/cdrskin_eng.html
|
||||
libburnia-project.org scdbackup.sourceforge.net/cdrskin_eng.html
|
||||
------------------------------------------------------------------------------
|
||||
Installation instructions at about line 60. First the legal stuff:
|
||||
------------------------------------------------------------------------------
|
||||
This all is under GPL.
|
||||
(See GPL reference, our clarification and commitment at the end of this text)
|
||||
------------------------------------------------------------------------------
|
||||
Based on and sub project of:
|
||||
libburn.pykix.org
|
||||
By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
|
||||
Copyright (C) 2006 Mario Danic, Thomas Schmitt
|
||||
|
||||
libburn.pykix.org is inspired by and in other components still containing
|
||||
parts of
|
||||
Libburn. By Derek Foreman <derek@signalmarketing.com> and
|
||||
Ben Jansens <xor@orodu.net>
|
||||
Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
|
||||
See toplevel README for an overview of the current copyright situation in
|
||||
libburn.pykix.org.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
My thanks to the above authors (except myself, of course) for making the
|
||||
following possible.
|
||||
|
||||
cdrskin. By Thomas Schmitt <scdbackup@gmx.net>
|
||||
Integrated sub project of libburn.pykix.org but also published via:
|
||||
Integrated sub project of libburnia-project.org but also published via:
|
||||
http://scdbackup.sourceforge.net/cdrskin_eng.html
|
||||
http://scdbackup.sourceforge.net/cdrskin-0.2.4.pl01.tar.gz
|
||||
Copyright (C) 2006 Thomas Schmitt
|
||||
http://scdbackup.sourceforge.net/cdrskin-1.1.0.tar.gz
|
||||
|
||||
Copyright (C) 2006-2011 Thomas Schmitt, provided under GPL version 2 or later.
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
On top of libburn there is implemented cdrskin 0.2.4, a limited cdrecord
|
||||
compatibility wrapper which allows to use some libburn features from
|
||||
the command line.
|
||||
Interested users of cdrecord are invited to participate in the development
|
||||
of cdrskin. Contact: scdbackup@gmx.net or libburn-hackers@pykix.org .
|
||||
We will keep copyright narrow but will of course acknowledge valuable
|
||||
contributions in a due way.
|
||||
|
||||
cdrskin is a limited cdrecord compatibility wrapper which allows to use
|
||||
most of the libburn features from the command line.
|
||||
|
||||
Important :
|
||||
This software is provided as is. There is no warranty implied and no
|
||||
protection against possible damages. You use this on your own risk.
|
||||
Don't blame me or other authors of libburn if anything goes wrong.
|
||||
Currently it is supported on GNU/Linux with kernels >= 2.4,
|
||||
on FreeBSD and on OpenSolaris.
|
||||
IDE drives under Linux 2.4. need kernel module ide-scsi.
|
||||
ATA and SATA drives under FreeBSD need kernel module atapicam.
|
||||
On other X/Open compliant systems there will only be emulated drives, but no
|
||||
direct MMC operation on real CD/DVD/BD drives.
|
||||
|
||||
I used it on my own risk with :
|
||||
SuSE 7.2, kernel 2.4.4, ide-scsi emulation, LITE-ON LTR48125S CD burner, 2002
|
||||
SuSE 9.0, kernel 2.4.21, ide-scsi emulation, LG GSA-4082B CD/DVD burner, 2004
|
||||
NEC ND-4570A CD/DVD burner, 2006
|
||||
RIP-14.4, kernel 2.6.14, no ide-scsi, with all above burners
|
||||
|
||||
It fails to compile or run on SuSE 6.4 (kernel 2.2.14).
|
||||
It does not find the IDE CD burner on SuSE 7.2 without ide-scsi.
|
||||
Other people sucessfully tested cdrskin on several kernel 2.6 based x86 Linux
|
||||
systems, including 64 bit systems. (Further reports are welcome.)
|
||||
By using this software you agree to the disclaimer at the end of this text
|
||||
"This software is provided as is. There is no warranty implied and ..."
|
||||
|
||||
|
||||
Compilation, First Glimpse, Installation
|
||||
|
||||
Obtain cdrskin-0.2.4.pl01.tar.gz ,take it to a directory of your choice and do:
|
||||
Obtain cdrskin-1.1.0.tar.gz, take it to a directory of your choice and do:
|
||||
|
||||
tar xzf cdrskin-0.2.4.pl01.tar.gz
|
||||
cd cdrskin-0.2.4
|
||||
tar xzf cdrskin-1.1.0.tar.gz
|
||||
cd cdrskin-1.1.0
|
||||
|
||||
Or obtain a libburn.pykix.org SVN snapshot,
|
||||
go into the toplevel directory of the snapshot (e.g. cd libburn_pykix ),
|
||||
and execute the autotools script ./bootstrap . Use autools version >= 1.7 .
|
||||
Within that directory execute:
|
||||
|
||||
Within that toplevel directory of either cdrskin-0.2.4 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
|
||||
install libburn in order to use this binary. Installation of libburn is
|
||||
beyond the scope of cdrskin. For this, see included libburn docs.
|
||||
This will already produce a cdrskin binary. But it will be necessary to
|
||||
install libburn in order to use this binary.
|
||||
|
||||
In order to surely get a standalone binary, execute
|
||||
|
||||
cdrskin/compile_cdrskin.sh
|
||||
|
||||
Version identification an help texts available afterwards:
|
||||
Version identification and help texts available afterwards:
|
||||
cdrskin/cdrskin -version
|
||||
cdrskin/cdrskin --help
|
||||
cdrskin/cdrskin -help
|
||||
man cdrskin/cdrskin.1
|
||||
|
||||
|
||||
Install (eventually as superuser) cdrskin to a directory where it can be found:
|
||||
The command for global installation of both, libburn and cdrskin is
|
||||
make install
|
||||
If the library libburn.so.4 is not found with a test run of cdrskin, then
|
||||
try whether command
|
||||
ldconfig
|
||||
makes it accessible. With the statically linked binary this should not matter.
|
||||
|
||||
With that static binary you may as well do the few necessary actions manually.
|
||||
If cdrskin was already installed by a previous version, or by "make install"
|
||||
in the course of this installation, then find out where:
|
||||
which cdrskin
|
||||
Copy your standalone binary to exactly the address which you get as reply
|
||||
Copy your standalone binary to exactly the address which you get as reply.
|
||||
E.g.:
|
||||
|
||||
cp cdrskin/cdrskin /usr/bin/cdrskin
|
||||
|
||||
@ -106,7 +74,15 @@ It is not necessary for the standalone cdrskin binary to have libburn
|
||||
installed, since it incorporates the necessary libburn parts at compile time.
|
||||
It will not collide with an installed version of libburn either.
|
||||
But libpthread must be installed on the system and glibc has to match. (See
|
||||
below for a way to create a statically linked binary.)
|
||||
below for a way to create a totally static linked binary.)
|
||||
|
||||
To install the man page, you may do: echo $MANPATH and choose one of the
|
||||
listed directories to copy the man-page under its ./man1 directory. Like:
|
||||
cp cdrskin/cdrskin.1 /usr/share/man/man1/cdrskin.1
|
||||
|
||||
Note: The content of the cdrskin tarball is essentially the complete libburn
|
||||
of the same version number. You may thus perform above steps in a local
|
||||
SVN copy of libburn or in a unpacked libburn tarball as well.
|
||||
|
||||
|
||||
Usage
|
||||
@ -121,58 +97,89 @@ The superuser should be able to see any usable drive and then set the
|
||||
permissions as needed. If this hangs then there is a drive with
|
||||
unexpected problems (locked, busy, broken, whatever). You might have to
|
||||
guess the address of your (non-broken) burner by other means, then.
|
||||
On Linux 2.4 this would be some /dev/sgN and on 2.6. some /dev/hdX.
|
||||
On Linux 2.4 this would be some /dev/sgN and on 2.6. some /dev/srM or /dev/hdX.
|
||||
|
||||
The output of cdrskin --devices might look like
|
||||
|
||||
0 dev='/dev/sg0' rwrwr- : '_NEC' 'DVD_RW ND-4570A'
|
||||
1 dev='/dev/sg1' rwrw-- : 'HL-DT-ST' 'DVDRAM GSA-4082B'
|
||||
0 dev='/dev/sr0' rwrwr- : '_NEC' 'DVD_RW ND-4570A'
|
||||
1 dev='/dev/sr1' rwrw-- : 'HL-DT-ST' 'DVDRAM GSA-4082B'
|
||||
|
||||
So full and insecure enabling of both for everybody would look like
|
||||
On Linux, full and insecure enabling of both for everybody would look like
|
||||
chmod a+rw /dev/sr0 /dev/hda
|
||||
This is equivalent to the traditional setup chmod a+x,u+s cdrecord.
|
||||
|
||||
chmod a+rw /dev/sg0 /dev/sg1
|
||||
On FreeBSD, device permissions are to be set in /etc/devfs.rules.
|
||||
On Solaris, pfexec privileges may be restricted to "basic,sys_devices".
|
||||
See below "System Dependend Drive Permission Examples".
|
||||
|
||||
I strongly discourage to run cdrskin with setuid root or via sudo !
|
||||
It is not checked for the necessary degree of hacker safety.
|
||||
Better consider to grant the necessary permissions to group "floppy"
|
||||
and to add users to it.
|
||||
|
||||
|
||||
A behavioral conflict is known between any burn software and demons like hald
|
||||
which probe CD drives. This can spoil burn runs for CD-R or CD-RW.
|
||||
You may have to keep your hald away from the drive. See for example
|
||||
http://www.freebsd.org/gnome/docs/halfaq.html
|
||||
|
||||
|
||||
Helpful with Linux kernel 2.4 is a special SCSI feature:
|
||||
It is possible to address a scsi(-emulated) drive via associated device files
|
||||
which are not listed by option --devices but point to the same SCSI addresses
|
||||
as listed device files. This addressing via e.g. /dev/sr0 or /dev/scd1 is
|
||||
compatible with generic read programs like dd and with write program growisofs.
|
||||
For finding /dev/sg1 from /dev/sr0, the program needs rw-access to both files.
|
||||
|
||||
|
||||
Usage examples
|
||||
|
||||
For options and recordable media classes see
|
||||
man 1 cdrskin
|
||||
|
||||
Get an overview of cdrecord style addresses of available devices
|
||||
cdrskin -scanbus
|
||||
cdrskin dev=ATA -scanbus
|
||||
cdrskin --devices
|
||||
|
||||
Note: Adresses reported with dev=ATA are to be used with prefix "ATA:". You may
|
||||
well use device file addresses as reported with --devices. Examples:
|
||||
dev=0,1,0 dev=/dev/sg1 dev=ATA:1,0,0 dev=/dev/hdc
|
||||
See also "Drive Addressing".
|
||||
Note: Address numbers have changed since cdrskin-0.2.2 in order to become
|
||||
compatible with cdrecord numbers. To get the old number scheme, use
|
||||
option --old_pseudo_scsi_adr . See also "Pseudo-SCSI Adresses".
|
||||
Sorry for any inconvenience.
|
||||
|
||||
Adresses reported with dev=ATA need prefix "ATA:". Address examples:
|
||||
dev=0,1,0 dev=ATA:1,0,0 dev=/dev/sg1 dev=/dev/hdc dev=/dev/sr0
|
||||
See also "Drive Addressing" below.
|
||||
|
||||
Obtain some info about the drive
|
||||
cdrskin dev=0,1,0 -checkdrive
|
||||
|
||||
Obtain some info about the drive and the inserted media
|
||||
cdrskin dev=0,1,0 -atip
|
||||
cdrskin dev=0,1,0 -atip -v -minfo
|
||||
|
||||
Thoroughly blank a CD-RW
|
||||
cdrskin -v dev=0,1,0 blank=all -eject
|
||||
Prepare CD-RW or DVD-RW for re-use, DVD-RAM or BD-RE for first use
|
||||
cdrskin -v dev=/dev/sg1 blank=as_needed -eject
|
||||
|
||||
Blank CD-RW sufficiently for making it ready for overwrite
|
||||
cdrskin -v dev=0,1,0 blank=fast -eject
|
||||
Format DVD-RW to avoid need for blanking before re-use
|
||||
cdrskin -v dev=0,1,0 blank=format_overwrite
|
||||
|
||||
Burn image file my_image.iso to CD
|
||||
cdrskin -v dev=0,1,0 speed=12 fs=8m -sao driveropts=burnfree padsize=300k \
|
||||
De-format DVD-RW to make it capable of multi-session again
|
||||
cdrskin -v dev=/dev/sr0 blank=deformat_sequential
|
||||
|
||||
Burn image file my_image.iso to media
|
||||
cdrskin -v dev=0,1,0 speed=12 fs=8m driveropts=burnfree padsize=300k \
|
||||
-eject my_image.iso
|
||||
|
||||
Burn a compressed afio archive to CD on-the-fly
|
||||
find . | afio -oZ - | cdrskin -v dev=0,1,0 fs=32m speed=8 -sao \
|
||||
driveropts=burnfree padsize=300k tsize=650m -
|
||||
Write multi-session to the same CD , DVD-R[W] or DVD+R[/DL]
|
||||
cdrskin dev=/dev/hdc padsize=300k -multi 1.iso
|
||||
cdrskin dev=/dev/hdc padsize=300k -multi 2.iso
|
||||
cdrskin dev=/dev/hdc padsize=300k -multi 3.iso
|
||||
cdrskin dev=/dev/hdc padsize=300k 4.iso
|
||||
|
||||
Burn 6 audio tracks from files with different formats to CD.
|
||||
Get multi-session info for option -C of program mkisofs:
|
||||
c_values=$(cdrskin dev=/dev/hdc -msinfo 2>/dev/null)
|
||||
mkisofs ... -C "$c_values" ...
|
||||
|
||||
Burn a compressed afio archive to media on-the-fly
|
||||
find . | afio -oZ - | cdrskin -v dev=0,1,0 fs=32m speed=8 \
|
||||
driveropts=burnfree padsize=300k -
|
||||
|
||||
Burn 6 audio tracks from files with different formats to CD (not to any DVD).
|
||||
Anything except .wav or .au files has to be converted into raw format first.
|
||||
See below "Audio CD" for specifications.
|
||||
ogg123 -d raw -f track01.cd /path/to/track1.ogg
|
||||
@ -181,151 +188,51 @@ See below "Audio CD" for specifications.
|
||||
madplay -o raw:track04.cd /path/to/track4.mp3
|
||||
mppdec --raw-le /path/to/track5.mpc track05.cd
|
||||
|
||||
cdrskin dev=0,1,0 blank=fast -eject speed=48 -sao \
|
||||
cdrskin -v dev=0,1,0 blank=fast -eject speed=48 -sao \
|
||||
-audio -swab track0[1-5].cd /path/to/track6.wav
|
||||
|
||||
|
||||
Usage example with http://scdbackup.sourceforge.net
|
||||
|
||||
Address may be a cdrecord-style "scsibus,target,lun" as listed with
|
||||
cdrskin -scanbus (and hopefully as listed with cdrecord -scanbus) :
|
||||
|
||||
export SCDBACKUP_SCSI_ADR="0,1,0"
|
||||
|
||||
or a device file address as listed by --devices with an accessible drive :
|
||||
|
||||
export SCDBACKUP_SCSI_ADR="/dev/sg1"
|
||||
|
||||
Set usage of cdrskin with appropriate options rather than cdrecord :
|
||||
|
||||
export SCDBACKUP_CDRECORD="cdrskin -v -v tao_to_sao_tsize=650m"
|
||||
|
||||
Run a backup :
|
||||
|
||||
scdbackup_home
|
||||
|
||||
|
||||
Restrictions
|
||||
|
||||
The convenient burn mode TAO is not available with libburn yet.
|
||||
Therefore it has to be defaulted to mode SAO which needs to know the track
|
||||
size in advance. non-cdrecord option tao_to_sao_tsize=650m causes each CD
|
||||
to get burned up to 650 MB regardless of the payload size.
|
||||
Several advanced CD related options of cdrecord are still unsupported.
|
||||
See output of command
|
||||
cdrskin --list_ignored_options
|
||||
If you have use cases for them, please report your wishes and expectations.
|
||||
|
||||
No multi session yet ... Please report your wishes.
|
||||
On the other hand, the capability of multi-session and of writing streams
|
||||
of unpredicted lenght surpass the current DVD capabilities of cdrecord.
|
||||
|
||||
|
||||
Inspiration and Standard
|
||||
|
||||
cdrskin combines the command line interface standard set by cdrecord with
|
||||
libburn, which is a control software for optical drives according to standard
|
||||
MMC-5. For particular CD legacy commands, standards MMC-3 and MMC-1 apply.
|
||||
|
||||
For the original meaning of cdrecord options see :
|
||||
man cdrecord
|
||||
(http://cdrecord.berlios.de/old/private/man/cdrecord-2.0.html)
|
||||
Do not bother Joerg Schilling with any cdrskin problems.
|
||||
(Be cursed if you install cdrskin as "cdrecord" without clearly forwarding
|
||||
this "don't bother Joerg" demand.)
|
||||
this "don't bother Joerg" demand.)
|
||||
|
||||
cdrskin does not contain any bytes copied from cdrecord's sources. Many bytes
|
||||
have been copied from the message output of cdrecord runs, though. I am
|
||||
thankful to Joerg Schilling for every single one of them.
|
||||
|
||||
Actually i, Thomas Schmitt, am a devoted user of cdrecord via my project
|
||||
scdbackup which still runs a bit better with cdrecord than with cdrskin. TAO.
|
||||
I have the hope that Joerg feels more flattered than annoyed by cdrskin.
|
||||
|
||||
|
||||
Drive Addressing
|
||||
|
||||
Drives get addressed either via their cdrecord-style addresses as listed
|
||||
with option -scanbus (see below "Pseudo-SCSI Adresses") or via the paths
|
||||
of device files.
|
||||
Not only device files listed by --devices may be used but also device files
|
||||
which via their major,minor numbers point to the same device driver as
|
||||
a listed device file.
|
||||
|
||||
Helpful with Linux kernel 2.4 is a special SCSI feature:
|
||||
It is possible to address a scsi(-emulated) drive via associated device files
|
||||
which are not listed by option --devices but point to the same SCSI addresses
|
||||
as listed device files. This addressing via e.g. /dev/sr0 or /dev/scd1 is
|
||||
compatible with generic read programs like dd and with write program growisofs.
|
||||
|
||||
Pseudo-SCSI Adresses
|
||||
|
||||
cdrecord and cdrskin share the syntax of SCSI addresses but not necessarily
|
||||
the meaning of the components. A cdrecord-style address for cdrskin
|
||||
[prefix:]scsibus,target,lun
|
||||
can be interpreted in two different modes.
|
||||
|
||||
Standard mode tries to be compatible to original cdrecord. This should be true
|
||||
with (emulated) SCSI where the /dev/sgN with is looked up with matching
|
||||
scsibus,target,lun as given by the operating system.
|
||||
With dev=ATA: or dev=ATAPI: the translation to /dev/hdX is purely literal
|
||||
but matches the cdrecord addresses on all systems tested so far:
|
||||
X = 'a' + 2 * scsibus + target
|
||||
where target only may have the values 0 or 1.
|
||||
|
||||
In this mode, option -scanbus will list only SCSI devices unless option
|
||||
dev=ATA or dev=ATAPI are given, which will suppress SCSI devices and only
|
||||
show IDE drives (i.e. /dev/hdX without ide-scsi emulation).
|
||||
|
||||
|
||||
In mode --old_pseudo_scsi_adr there is a scsibus,target,lun representation
|
||||
which has nothing to do with SCSI and thus is not compatible to cdrecord.
|
||||
Each number triple corresponds either to a device file address or to a
|
||||
libburn drive number.
|
||||
Component "scsibus" indicates the translation method. Defined busses are:
|
||||
0 target is the libburn drivenumber as listed with --devices
|
||||
1 associated to device file /dev/sgN , target chooses N
|
||||
2 associated to device file /dev/hdX , target 0='a', 1='b' ..., 25='z'
|
||||
|
||||
So "1,1,0" is /dev/sg1, "2,3,0" is /dev/hdd, "0,2,0" is libburn drive #2 at
|
||||
some unspecified device file.
|
||||
This scheme shall help to keep cdrecord-style addresses stable and exchangeable
|
||||
between users without excluding drives with unexpected device addresses.
|
||||
The numbering on bus 0 is prone to arbitrary changes caused by changes in
|
||||
drive accessability.
|
||||
Further busses may emerge as libburn evolves. "prefix" and "lun" may get
|
||||
a meaning. To stay upward compatible, use addresses as printed by -scanbus.
|
||||
|
||||
User Defined Device Address Translation
|
||||
|
||||
Some programs or users have their own ideas about the address of their burner.
|
||||
K3b 0.10 for example derives cdrecord addresses by own examination of the
|
||||
devices and not by calling cdrecord -scanbus.
|
||||
Standard mode will hopefully be fully compatible with their ideas.
|
||||
|
||||
Old frontends which do not know dev=ATA or dev=ATAPI and which do ask their
|
||||
"cdrecord" via -scanbus may be well served with option --old_pseudo_scsi_adr .
|
||||
|
||||
To direct any remaining stubborn callers to the appropriate drives, cdrskin
|
||||
allows to define device address aliases. Like
|
||||
cdrskin dev_translation=+1,0,0+/dev/sg1 \
|
||||
dev_translation=+ATA:1,0,0+/dev/sg1 \
|
||||
dev_translation=-"cd+dvd"-0,1,0 \
|
||||
...
|
||||
Any of the addresses dev=1,0,0, dev=ATA:1,0,0, dev=cd+dvd will be mapped to
|
||||
/dev/sg1 resp. to 0,1,0.
|
||||
The first character after "dev_translation=" defines the character which
|
||||
separates the two parts of the translation pair. (Above: "+" and "-".)
|
||||
|
||||
In K3b 0.10 it is possible to employ alternative writer programs by setting
|
||||
their full path (e.g. /usr/bin/cdrskin) in menu
|
||||
Settings:Configure K3b...:Programs:Search Path
|
||||
and to make them default in menu
|
||||
Settings:Configure K3b...:Programs:Programs:
|
||||
A suitable setting for "cdrecord" in menu
|
||||
Settings:Configure K3b...:Programs:User Parameters
|
||||
would then probably be
|
||||
-v dev_translation=+1,0,0+/dev/sg1
|
||||
You will learn from button "Show Debugging Output" after a failed burn run
|
||||
what cdrecord command was used with what address "dev=...". This address "..."
|
||||
will be the right one to replace "1,0,0" in above example.
|
||||
Many thanks to Andy Polyakov for his dvd+rw-tools
|
||||
http://fy.chalmers.se/~appro/linux/DVD+RW/tools
|
||||
which provide me with examples and pointers into MMC specs for DVD writing.
|
||||
|
||||
|
||||
Startup Files
|
||||
|
||||
If not --no_rc is the first argument then cdrskin attempts on startup to read
|
||||
arguments from the following three files:
|
||||
/etc/defaults/cdrskin
|
||||
/etc/default/cdrskin
|
||||
/etc/opt/cdrskin/rc
|
||||
/etc/cdrskin/cdrskin.conf
|
||||
$HOME/.cdrskinrc
|
||||
The files are read in the sequence given above.
|
||||
Each readable line is treated as one single argument. No extra blanks.
|
||||
@ -334,11 +241,9 @@ A first character '#' marks a comment, empty lines are ignored.
|
||||
Example content of a startup file:
|
||||
# This is the default device
|
||||
dev=0,1,0
|
||||
# To accomodate to eventual remnant cdrskin-0.2.2 addresses
|
||||
dev_translation=+1,0,0+0,1,0
|
||||
|
||||
# Some more options
|
||||
--fifo_start_empty
|
||||
fifo_start_at=0
|
||||
fs=16m
|
||||
|
||||
|
||||
@ -368,8 +273,156 @@ I myself am not into audio. So libburn-hackers@pykix.org might be the
|
||||
best address for suggestions, requests and bug reports.
|
||||
|
||||
|
||||
DVD+RW , DVD-RAM , BD-RE
|
||||
|
||||
These random access media get treated as blank media regardless wether they
|
||||
hold data or not. Options -audio and -multi are not allowed. Only one track
|
||||
is allowed. -toc does not return information about the media content.
|
||||
Speed is counted in DVD units (i.e. 1x = 1,385,000 bytes/second) or BD units
|
||||
(1x = 4,495,625 bytes/second). Currently there is no difference between -sao
|
||||
and -tao. If ever, then -tao will be the mode which preserves the current
|
||||
behavior.
|
||||
|
||||
BD-RE media need formatting before first use. cdrskin option "blank=as_needed"
|
||||
recognizes unformatted BD-RE and applies a lengthy formatting run.
|
||||
|
||||
During write operations DVD-RAM and BD-RE automatically apply Defect
|
||||
Management. This usually slows them down to half nominal speed. If drive
|
||||
and media produce flawless results anyway, then one can try to reach full
|
||||
nominal speed by option "stream_recording=on".
|
||||
In this case bad blocks are not detected during write and not even previously
|
||||
known bad blocks are avoided. So you have to make your own readability tests
|
||||
and go back to half speed as soon as the first read errors show up.
|
||||
Instead of "on" one may also set a start address for stream recording.
|
||||
Like "stream_recording=100m". This will write slowly to the first 100 MB of
|
||||
the media and accelerate when writing to higher addresses.
|
||||
|
||||
Option --grow_overwriteable_iso allows -multi (although unneeded), enables
|
||||
-msinfo and -toc, and makes blank=fast an invalidator for ISO filesystems
|
||||
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 , DVD-R , DVD-R DL
|
||||
|
||||
DVD-RW are usable if formatted to state "Restricted Overwrite" or if in state
|
||||
"Sequential Recording". DVD-R are always in sequential state. DVD-R DL are
|
||||
always sequential and incapable of multi-session.
|
||||
|
||||
"Sequential" is the state of unused media and of media previously blanked
|
||||
or written by cdrecord. dvd+rw-format -blank can also achieve this state.
|
||||
The according cdrskin option is blank=deformat_sequential .
|
||||
If "Incremental Streaming" is available, then sequential media are capable
|
||||
of multi-session like CD-R[W]. (But not capable of -audio recording.)
|
||||
This means they need option -multi to stay appendable, need to be blanked
|
||||
to be writeable from start, return useable info with -toc and -msinfo,
|
||||
eventually perform appending automatically.
|
||||
Without Incremental Streaming offered by the drive, only write mode DAO is
|
||||
available with sequential DVD-R[W]. It only works with blank media, allows only
|
||||
one single track, no -multi, and demands a fixely predicted track size.
|
||||
(growisofs uses it with DVD-R[W] if option -dvd-compat is given.)
|
||||
|
||||
Overwriteable DVD-RW behave much like DVD+RW. "Restricted" refers only to the
|
||||
granularity of random access and block size which have always to be aligned to
|
||||
full 32 kB. Sequential DVD-RW are converted into overwriteable DVD-RW by
|
||||
cdrskin dev=... -v blank=format_overwrite
|
||||
(Command dvd+rw-format -force can achieve Restricted Overwrite, too.)
|
||||
|
||||
Formatting or first use of freshly formatted DVD-RW can produce unusual noises
|
||||
from the drive and last several minutes. Depending on mutual compatibility of
|
||||
drive and media, formatting can yield unusable media. It seems that those die
|
||||
too on blanking by cdrecord, dvd+rw-format or cdrskin. Perils of DVD-RW.
|
||||
|
||||
There are three DVD-RW formatting variants with cdrskin currently:
|
||||
|
||||
blank=format_overwrite uses "DVD-RW Quick" formatting (MMC-type 15h)
|
||||
and writes a first session of 128 MiB. This leads to media which are expandable
|
||||
and random addressable by cdrskin.
|
||||
|
||||
blank=format_overwrite_quickest uses "DVD-RW Quick" formatting (type 15h) too,
|
||||
but leaves the media in "intermediate" state. In the first session of writing
|
||||
one may only write sequentially to such a DVD. After that, it gets random
|
||||
addressable by cdrskin. DVD-ROM drives might show ill behavior with them.
|
||||
|
||||
blank=format_overwrite_full uses preferrably "Full Format" (type 00h).
|
||||
This formatting lasts as long as writing a full DVD. It includes writing of
|
||||
lead-out which is said to be good for DVD ROM compatibility.
|
||||
|
||||
De-formatting options are available to make overwriteable DVD-RW sequential:
|
||||
|
||||
blank=deformat_sequential performs thorough blanking of all states of DVD-RW.
|
||||
blank=all and blank=fast perform the same thorough blanking, but refuse to do
|
||||
this with overwriteable DVD-RW, thus preserving their formatting. The specs
|
||||
allow minimal blanking but the resulting media on my drives offer no
|
||||
Incremental Streaming afterwards. So blank=fast will do full blanking.
|
||||
|
||||
blank=deformat_sequential_quickest is faster but might yield DAO-only media.
|
||||
|
||||
|
||||
DVD+R , DVD+R DL , BD-R
|
||||
|
||||
From the view of cdrskin they behave much like DVD-R. Each track gets wrapped
|
||||
into an own session, though.
|
||||
|
||||
DVD+R DL appear as extra large DVD+R. cdrskin does not allow to set the address
|
||||
of the layer break where a reading drive might show some delay while switching
|
||||
between both media layers.
|
||||
|
||||
BD-R are sold unformatted blank. If used without initial formatting then the
|
||||
drive is supposed to format them to maximum payload size with no Defect
|
||||
Management (see also above with BD-RE).
|
||||
If Defect Management is desired then BD-R need to be formatted before the
|
||||
first attempt to write a session to them.
|
||||
blank=format_if_needed will detect the situation and eventually apply
|
||||
default sized Defect Management formatting.
|
||||
blank=format_defectmgt_* will apply non-default parameters to formatting.
|
||||
|
||||
|
||||
Emulated Drives
|
||||
|
||||
cdrskin can use filesystem objects as emulated drives. Regular files or block
|
||||
devices appear similar to DVD-RAM. Other file types resemble blank DVD-R.
|
||||
Necessary precondition is option --allow_emulated_drives which is not accepted
|
||||
if cdrskin took another user identity because of the setuid bit of its access
|
||||
permissions.
|
||||
Addresses of emulated drives begin with prefix "stdio:". E.g.
|
||||
dev=stdio:/tmp/my_pseudo_drive
|
||||
|
||||
For safety reasons the superuser is only allowed to use /dev/null as emulated
|
||||
drive. See man page section FILES for a way to lift that ban.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Special compilation variations
|
||||
|
||||
All following options of ./configure and cdrskin/compile_cdrskin.sh are
|
||||
combinable. After runs of ./configure do as next:
|
||||
make clean ; make
|
||||
|
||||
In some situations Linux may deliver a better write performance to drives if
|
||||
the track input is read with O_DIRECT (see man 2 open). The API call
|
||||
burn_os_open_track_src() and the input readers of cdrskin and libburn fifo
|
||||
can be told to use this peculiar read mode by:
|
||||
--enable-track-src-odirect
|
||||
|
||||
But often cdrskin option dvd_obs=64k will yield even better performance in
|
||||
such a situation. 64k can be made default at compile time by
|
||||
cdrskin/compile_cdrskin.sh -dvd_obs_64k
|
||||
It can also be enabled at configure time by
|
||||
./configure ... --enable-dvd-obs-64k ...
|
||||
|
||||
Alternatively the transport of SCSI commands can be done via libcdio-0.83.
|
||||
You may install it and re-run libburn's ./configure with option
|
||||
--enable-libcdio
|
||||
|
||||
You may get a (super fat) statically linked binary by :
|
||||
cdrskin/compile_cdrskin.sh -static
|
||||
if your system supports static linking, at all. This will not help with kernels
|
||||
@ -385,12 +438,114 @@ It will not read startup files, will abort on option dev_translation= ,
|
||||
will not have a fifo buffer, and will not be able to put out help texts or
|
||||
debugging messages.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
System Dependend Drive Permission Examples
|
||||
|
||||
Accessing the optical drives requires privileges which usually are granted
|
||||
only to the superuser. Linux, FreeBSD and Solaris offer quite different
|
||||
approaches for avoiding the need for unrestricted privileges.
|
||||
|
||||
First check whether some friendly system setting already allows you to
|
||||
access the drives as normal user:
|
||||
cdrskin --devices
|
||||
Those drives of which you see address and type strings are already usable.
|
||||
|
||||
If there remain drives invisible which the superuser can see by the same
|
||||
command, then the following examples might help:
|
||||
|
||||
---------------------
|
||||
On all three systems:
|
||||
---------------------
|
||||
Add the authorized users of CD drives to group "floppy" in /etc/group.
|
||||
If missing: create this group.
|
||||
Changes to /etc/group often only affect new login sessions. So log out and in
|
||||
before making the first tests.
|
||||
|
||||
---------
|
||||
On Linux:
|
||||
---------
|
||||
Allow rw-access to the drives
|
||||
chgrp floppy /dev/sr0 /dev/sr1
|
||||
chmod g+rw /dev/sr0 /dev/sr1
|
||||
It might be necessary to perform chgrp and chmod after each reboot or to
|
||||
edit distro dependent device configuration files for permanent settings.
|
||||
|
||||
-----------
|
||||
On FreeBSD:
|
||||
-----------
|
||||
Edit /etc/devfs.rules and make sure to have these lines
|
||||
[localrules=10]
|
||||
add path 'acd*' mode 0664 group floppy
|
||||
add path 'cd*' mode 0664 group floppy
|
||||
add path 'pass*' mode 0664 group floppy
|
||||
add path 'xpt*' mode 0664 group floppy
|
||||
[localrules=5]
|
||||
add path 'pass*' mode 0664 group floppy
|
||||
add path 'cd*' mode 0664 group floppy
|
||||
add path 'xpt*' mode 0664 group floppy
|
||||
add path 'acd*' mode 0664 group floppy
|
||||
|
||||
Edit /etc/rc.conf and add the following line if missing
|
||||
devfs_system_ruleset="localrules"
|
||||
|
||||
This gets into effect by reboot or by command
|
||||
/etc/rc.d/devfs start
|
||||
|
||||
-----------
|
||||
On Solaris:
|
||||
-----------
|
||||
Run cdrskin by
|
||||
pfexec cdrskin ...arguments...
|
||||
|
||||
The following settings will make pfexec keep original UID and EUID and prevent
|
||||
most superuser powers. Be aware that you still can manipulate all device files
|
||||
if you have the file permissions for that.
|
||||
Full root privileges for cdrskin can then be aquired only by command su.
|
||||
|
||||
Edit /etc/security/exec_attr and add this line to the other "Media Backup"
|
||||
lines:
|
||||
Media Backup:solaris:cmd:::/usr/local/bin/cdrskin:privs=basic,sys_devices
|
||||
Edit /etc/user_attr and add profile "Media Backup" to the user's line:
|
||||
thomas::::profiles=Media Backup,Primary Administrator;roles=root
|
||||
See also man privileges, man exec_attr, man user_attr.
|
||||
|
||||
Then allow the group r-access to the drives
|
||||
pfexec chgrp floppy /dev/rdsk/c3t0d0s2 /dev/rdsk/c4t0d0s2
|
||||
pfexec chmod g+r /dev/rdsk/c3t0d0s2 /dev/rdsk/c4t0d0s2
|
||||
The last two commands have to be executed after each boot. I do not know
|
||||
the relevant device configuration files yet.
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Project aspects and legal stuff
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Important Disclaimer :
|
||||
|
||||
This software is provided as is. There is no warranty implied and no
|
||||
protection against possible damages. You use this on your own risk.
|
||||
Don't blame me or other authors of libburn if anything goes wrong.
|
||||
|
||||
Actually, in case of severe trouble, nearly always the drive and the media
|
||||
are the cause. Any mistake of the burn program is supposed to be caught
|
||||
by the drive's firmware and to lead to mere misburns.
|
||||
The worst mishaps which hit the author imposed the need to reboot the
|
||||
system because of drives gnawing endlessly on ill media. Permanent hardware
|
||||
damage did not occur in 3.5 years of development. But one never knows ...
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
Interested users are invited to participate in the development of cdrskin.
|
||||
Contact: scdbackup@gmx.net or libburn-hackers@pykix.org .
|
||||
We will keep copyright narrow but will of course acknowledge valuable
|
||||
contributions in a due way.
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
the Free Software Foundation; either version 2 of the License, or
|
||||
(at your option) any later version.
|
||||
it under the terms of the GNU General Public License version 2 or later
|
||||
as published by the Free Software Foundation.
|
||||
|
||||
This program is distributed in the hope that it will be useful,
|
||||
but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
@ -402,33 +557,17 @@ debugging messages.
|
||||
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
cdrskin is currently copyright Thomas Schmitt only.
|
||||
It adopts the following commitment by the toplevel copyright holders:
|
||||
------------------------------------------------------------------------------
|
||||
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-2010 Mario Danic, Thomas Schmitt
|
||||
|
||||
We, the copyright holders, agree on the interpretation that
|
||||
dynamical linking of our libraries constitutes "use of" and
|
||||
not "derivation from" our work in the sense of GPL, provided
|
||||
those libraries are compiled from our unaltered code.
|
||||
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.
|
||||
|
||||
Thus you may link our libraries dynamically with applications
|
||||
which are not under GPL. You may distribute our libraries and
|
||||
application tools in binary form, if you fulfill the usual
|
||||
condition of GPL to offer a copy of the source code -altered
|
||||
or unaltered- under GPL.
|
||||
|
||||
We ask you politely to use our work in open source spirit
|
||||
and with the due reference to the entire open source community.
|
||||
|
||||
If there should really arise the case where above clarification
|
||||
does not suffice to fulfill a clear and neat request in open source
|
||||
spirit that would otherwise be declined for mere formal reasons,
|
||||
only in that case we will duely consider to issue a special license
|
||||
covering only that special case.
|
||||
It is the open source idea of responsible freedom which will be
|
||||
decisive and you will have to prove that you exhausted all own
|
||||
means to qualify for GPL.
|
||||
|
||||
For now we are firmly committed to maintain one single license: GPL.
|
||||
|
||||
signed for cdrskin: Thomas Schmitt
|
||||
|
@ -1,193 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -x
|
||||
|
||||
# This script was used for producing cdrskin-0.2.4.pl01 from
|
||||
# the svn snapshot made for cdrskin-0.2.4.pl00 and some changes
|
||||
# in a patch directory.
|
||||
#
|
||||
# Script results are a source tarball and two binaries
|
||||
# one dynamic and one static in respect to system libs.
|
||||
# Both binaries are static in respect to libburn.
|
||||
#
|
||||
# The script is to be run in the directory above the toplevel
|
||||
# directory of libburn resp. cdrskin development.
|
||||
#
|
||||
# libburn version used: http://libburn.pykix.org
|
||||
# Downloaded by:
|
||||
# $ svn co http://libburn-svn.pykix.org/trunk libburn_pykix
|
||||
# packed up in a tarball just to save it from inadverted changes by
|
||||
# $ tar czf libburn_svn.tgz libburn_pykix
|
||||
# Then it went through cdrskin/add_ts_changes_to_libburn_0_2_4 where
|
||||
# the following svn snapshot emerged.
|
||||
original="./cdrskin-0.2.4.svn.tar.gz"
|
||||
|
||||
# The top level directory in that snapshot is named
|
||||
intermediate="./cdrskin-0.2.4"
|
||||
|
||||
# My changes are in
|
||||
changes="./cdrskin-0.2.4.patch01"
|
||||
|
||||
# Version parameters
|
||||
skin_release="0.2.4"
|
||||
patch_level=".pl01"
|
||||
skin_rev="$skin_release""$patch_level"
|
||||
|
||||
# The result directory and the name of the result tarballs
|
||||
target="./cdrskin-${skin_release}"
|
||||
cdrskin_tarball="./cdrskin-${skin_rev}.tar.gz"
|
||||
cdrskin_tarball_svn="./cdrskin-${skin_rev}.svn.tar.gz"
|
||||
|
||||
# Where to work
|
||||
compile_dir="$target"
|
||||
compile_cmd="./cdrskin/compile_cdrskin.sh"
|
||||
compile_static_opts="-static"
|
||||
compile_result="cdrskin/cdrskin"
|
||||
|
||||
bintarget_dynamic="cdrskin_${skin_rev}-x86-suse9_0"
|
||||
bintarget_static="$bintarget_dynamic"-static
|
||||
|
||||
if test -d "$changes"
|
||||
then
|
||||
dummy=dummy
|
||||
else
|
||||
echo "$0 : FATAL : no directory $changes" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for i in "$target" "$intermediate"
|
||||
do
|
||||
if test -e "$i"
|
||||
then
|
||||
echo "$0 : FATAL : already existing $i" >&2
|
||||
exit 2
|
||||
fi
|
||||
done
|
||||
|
||||
if test -f "$original"
|
||||
then
|
||||
dummy=dummy
|
||||
else
|
||||
echo "$0 : FATAL : no file $original" >&2
|
||||
exit 3
|
||||
fi
|
||||
|
||||
|
||||
# Unpack SVN snapshot.
|
||||
tar xzf "$original"
|
||||
|
||||
|
||||
# Rename the directory to the cdrskin name
|
||||
if test "$intermediate" = "$target"
|
||||
then
|
||||
dummy=dummy
|
||||
else
|
||||
mv "$intermediate" "$target"
|
||||
fi
|
||||
|
||||
|
||||
# Copy the changes from the patch tree
|
||||
#
|
||||
cdrskin_dir="$changes"/cdrskin
|
||||
libburn_dir="$changes"/libburn
|
||||
test_dir="$changes"/test
|
||||
cdrskin_target="$target"/cdrskin
|
||||
libburn_target="$target"/libburn
|
||||
test_target="$target"/test
|
||||
|
||||
# Create version timestamp
|
||||
timestamp="$(date -u '+%Y.%m.%d.%H%M%S')"
|
||||
echo "$timestamp"
|
||||
echo '#define Cdrskin_timestamP "'"$timestamp"' (pl01)"' \
|
||||
>"$cdrskin_dir"/cdrskin_timestamp.h
|
||||
|
||||
#
|
||||
# Do the repair of patch01
|
||||
#
|
||||
# configure.ac used macro AM_CONFIG_HEADER() and thus disabled all
|
||||
# other compile time configure macros. Among them were those which
|
||||
# enabled 64 bit off_t in libburn. They were always set in cdrskin
|
||||
# so that there was a 64<>32 bit mess-up.
|
||||
# Negative consequences are to be expected at least with big-endian
|
||||
# processors (i.e non-Intel compatible, MSB-first) on systems with
|
||||
# 32 bit off_t default.
|
||||
#
|
||||
# bootstrap called a program named autoheader which is obsolete
|
||||
# without the AM_CONFIG_HEADER macro.
|
||||
#
|
||||
cp -a "$changes"/bootstrap "$target"
|
||||
cp -a "$changes"/configure.ac "$target"
|
||||
|
||||
# Unlike cdrskin, libburner is not depending on 64 bit off_t
|
||||
# so the according code part has been removed. A similar remedy in
|
||||
# cdrskin took place in version 0.2.5. Its consequences are wider
|
||||
# than would be appropriate for this patch.
|
||||
cp -a "$test_dir"/libburner.c "$test_target"
|
||||
|
||||
# Mention changed tarball name
|
||||
cp -a "$cdrskin_dir"/README "$cdrskin_target"
|
||||
|
||||
# Fetch this script
|
||||
cp -a "$cdrskin_dir"/add_ts_changes_to_libburn_0_2_4_patch01 "$cdrskin_target"
|
||||
|
||||
# Mark the patch
|
||||
cp -a "$cdrskin_dir"/cdrskin_timestamp.h "$cdrskin_target"
|
||||
|
||||
#
|
||||
# end of repair for patch01
|
||||
#
|
||||
|
||||
|
||||
# Make SVN state tarball for the libburn team
|
||||
tar czf "$cdrskin_tarball_svn" "$target"
|
||||
|
||||
|
||||
# Get over dependecy on autotools. Rely only on cc, make et. al.
|
||||
# This is not the same as "make dist" but i can do it without
|
||||
# having to evaluate the quality of said "make dist"
|
||||
#
|
||||
( cd "$target" ; ./bootstrap )
|
||||
|
||||
# Remove unwanted stuff after bootstrap
|
||||
for i in "$target"/autom4te.cache
|
||||
do
|
||||
if echo "$i" | grep '\*' >/dev/null
|
||||
then
|
||||
dummy=dummy
|
||||
else
|
||||
if test -e "$i"
|
||||
then
|
||||
rm -rf "$i"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
# Pack it up to the new libburn+cdrskin-tarball
|
||||
tar czf "$cdrskin_tarball" "$target"
|
||||
|
||||
# Produce a static and a dynamic binary
|
||||
(
|
||||
cd "$compile_dir" || exit 1
|
||||
./configure
|
||||
make
|
||||
$compile_cmd -do_strip
|
||||
cp "$compile_result" "../$bintarget_dynamic"
|
||||
if test -n "$compile_static_opts"
|
||||
then
|
||||
$compile_cmd $compile_static_opts -do_strip
|
||||
cp "$compile_result" "../$bintarget_static"
|
||||
fi
|
||||
)
|
||||
|
||||
# Remove the build area
|
||||
# Disable this for debugging the merge process
|
||||
rm -rf "$target"
|
||||
|
||||
# Show the result
|
||||
./"$bintarget_dynamic" -version
|
||||
./"$bintarget_static" -version
|
||||
ls -l "$cdrskin_tarball"
|
||||
ls -l "$bintarget_dynamic"
|
||||
ls -l "$bintarget_static"
|
||||
|
246
cdrskin/add_ts_changes_to_libburn_1_1_0
Executable file
246
cdrskin/add_ts_changes_to_libburn_1_1_0
Executable file
@ -0,0 +1,246 @@
|
||||
#!/bin/sh
|
||||
|
||||
set -x
|
||||
|
||||
# This script documents how this cdrskin version was derived from
|
||||
# a vanilla libburn version. It is not intended nor needed for any
|
||||
# use of cdrskin but included here only to show the technical
|
||||
# relationship between both projects - which are close friends
|
||||
# and issue roughly the same software.
|
||||
#
|
||||
# Package maintainers are advised to cover rather libburn than
|
||||
# cdrskin unless they put only emphasis on the cdrecord emulation
|
||||
# provided by cdrskin. libburn contains cdrskin - cdrskin is an
|
||||
# oscillating, friendly and coordinated fork of libburn.
|
||||
#
|
||||
# Script results are a source tarball and two binaries
|
||||
# one dynamic and one static in respect to system libs.
|
||||
# Both binaries are static in respect to libburn.
|
||||
#
|
||||
# The script is to be run in the directory above the toplevel
|
||||
# directory of libburn resp. cdrskin development.
|
||||
#
|
||||
|
||||
# The top level directory in the SVN snapshot is named
|
||||
intermediate="./libburn_pykix"
|
||||
|
||||
# libburn source used: http://libburnia.pykix.org
|
||||
# Downloaded by:
|
||||
# $ svn co http://libburnia-svn.pykix.org/libburn/tags/... $intermediate
|
||||
# packed up in a tarball just to save it from inadverted changes by
|
||||
# $ tar czf libburn_svn.tgz $intermediate
|
||||
original="./libburn_svn_release.tgz"
|
||||
# Historic moments:
|
||||
# original="./libburn_svn_A60815.tgz"
|
||||
# original="./libburn_cdrskin_A60819.tgz"
|
||||
|
||||
|
||||
# My changes are in $changes , mainly in $changes/cdrskin
|
||||
changes="./libburn-release"
|
||||
|
||||
skin_release="1.1.0"
|
||||
patch_level=""
|
||||
# patch_level=".pl00"
|
||||
skin_rev="$skin_release""$patch_level"
|
||||
|
||||
# The result directory and the name of the result tarballs
|
||||
target="./cdrskin-${skin_release}"
|
||||
cdrskin_tarball="./cdrskin-${skin_rev}.tar.gz"
|
||||
cdrskin_tarball_svn="./cdrskin-${skin_rev}.svn.tar.gz"
|
||||
|
||||
# (This once earned me an embarrassingly blooping source tarball)
|
||||
# compile_dir="$changes"
|
||||
|
||||
compile_dir="$target"
|
||||
compile_cmd="./cdrskin/compile_cdrskin.sh"
|
||||
compile_static_opts="-static"
|
||||
compile_result="cdrskin/cdrskin"
|
||||
|
||||
man_to_html_cmd="./cdrskin/convert_man_to_html.sh"
|
||||
man_page_html="cdrskin/man_1_cdrskin.html"
|
||||
|
||||
# bintarget_dynamic="cdrskin_${skin_rev}-x86-suse9_0"
|
||||
bintarget_dynamic="cdrskin_${skin_rev}-amd64-suse10_2"
|
||||
bintarget_static="$bintarget_dynamic"-static
|
||||
|
||||
if test -d "$changes"
|
||||
then
|
||||
dummy=dummy
|
||||
else
|
||||
echo "$0 : FATAL : no directory $changes" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
for i in "$target" "$intermediate"
|
||||
do
|
||||
if test -e "$i"
|
||||
then
|
||||
echo "$0 : FATAL : already existing $i" >&2
|
||||
exit 2
|
||||
fi
|
||||
done
|
||||
|
||||
if test -f "$original"
|
||||
then
|
||||
dummy=dummy
|
||||
else
|
||||
echo "$0 : FATAL : no file $original" >&2
|
||||
exit 3
|
||||
fi
|
||||
|
||||
|
||||
# Unpack SVN snapshot.
|
||||
tar xzf "$original"
|
||||
|
||||
|
||||
# Rename the directory to the cdrskin name
|
||||
mv "$intermediate" "$target"
|
||||
|
||||
|
||||
# Copy the changes from the development tree
|
||||
#
|
||||
cdrskin_dir="$changes"/cdrskin
|
||||
libburn_dir="$changes"/libburn
|
||||
cdrskin_target="$target"/cdrskin
|
||||
libburn_target="$target"/libburn
|
||||
|
||||
# Create version timestamp
|
||||
# timestamp="$(date -u '+%Y.%m.%d.%H%M%S')"
|
||||
# echo "$timestamp"
|
||||
# echo '#define Cdrskin_timestamP "'"$timestamp"'"' >"$cdrskin_dir"/cdrskin_timestamp.h
|
||||
|
||||
# Add the cdrskin files
|
||||
if test -e "$cdrskin_target"
|
||||
then
|
||||
rm -rf "$cdrskin_target"
|
||||
fi
|
||||
cp -a "$cdrskin_dir" "$cdrskin_target"
|
||||
|
||||
# Remove copied vim.swp and binaries
|
||||
rm "$cdrskin_target"/.*.swp
|
||||
rm "$cdrskin_target"/.*.swo
|
||||
rm "$cdrskin_target"/*.o
|
||||
rm "$cdrskin_target"/cdrfifo
|
||||
rm "$cdrskin_target"/cdrskin
|
||||
rm "$cdrskin_target"/cleanup
|
||||
for i in std new make old
|
||||
do
|
||||
if test -e "$cdrskin_target"/cdrskin_"$i"
|
||||
then
|
||||
rm "$cdrskin_target"/cdrskin_"$i"
|
||||
fi
|
||||
done
|
||||
|
||||
# Remove eventual SVN stuff from cdrskin directory
|
||||
for i in .deps .dirstamp .libs
|
||||
do
|
||||
if test -e "$cdrskin_target"/"$i"
|
||||
then
|
||||
rm -rf "$cdrskin_target"/"$i"
|
||||
fi
|
||||
done
|
||||
|
||||
# Remove GIFs of cdrskin_eng.html
|
||||
rm "$cdrskin_target"/doener_*.gif "$cdrskin_target"/doener_*.png
|
||||
|
||||
# Remove automatically generated HTML man page
|
||||
rm "$cdrskin_target"/man_1_cdrskin.html
|
||||
|
||||
# Remove all add_ts_changes_to_libburn besides this one
|
||||
for i in "$cdrskin_target"/add_ts_changes_to_libburn*
|
||||
do
|
||||
if test $(basename "$0") = $(basename "$i")
|
||||
then
|
||||
dummy=dummy
|
||||
else
|
||||
rm $i
|
||||
fi
|
||||
done
|
||||
|
||||
# Remove libcevap
|
||||
rm -rf "$target"/libcevap
|
||||
|
||||
|
||||
# Remove unwanted SVN stuff (TODO: avoid downloading it)
|
||||
for i in "$target"/.svn "$target"/*/.svn
|
||||
do
|
||||
if test "$i" = "$target"'/*/.svn'
|
||||
then
|
||||
dummy=dummy
|
||||
else
|
||||
if test -e "$i"
|
||||
then
|
||||
rm -rf "$i"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
|
||||
# Make SVN state tarball for the libburn team
|
||||
tar czf "$cdrskin_tarball_svn" "$target"
|
||||
|
||||
|
||||
# Get over dependecy on autotools. Rely only on cc, make et. al.
|
||||
# This is not the same as "make dist" but i can do it without
|
||||
# having to evaluate the quality of said "make dist"
|
||||
#
|
||||
( cd "$target" ; ./bootstrap )
|
||||
|
||||
# Remove unwanted stuff after bootstrap
|
||||
for i in "$target"/autom4te.cache
|
||||
do
|
||||
if echo "$i" | grep '\*' >/dev/null
|
||||
then
|
||||
dummy=dummy
|
||||
else
|
||||
if test -e "$i"
|
||||
then
|
||||
rm -rf "$i"
|
||||
fi
|
||||
fi
|
||||
done
|
||||
|
||||
# Repair non-portable shell code output of ./bootstrap
|
||||
(
|
||||
cd "$compile_dir" || exit 1
|
||||
sed -e 's/^for ac_header in$/test -z 1 \&\& for ac_header in dummy/' \
|
||||
< ./configure > ./configure-repaired
|
||||
if test "$?" = 0
|
||||
then
|
||||
echo "$0: Empty 'for ac_header in' found in configure." >&2
|
||||
fi
|
||||
mv ./configure-repaired ./configure
|
||||
chmod a+rx,go-w,u+w ./configure
|
||||
)
|
||||
|
||||
# Pack it up to the new libburn+cdrskin-tarball
|
||||
tar czf "$cdrskin_tarball" "$target"
|
||||
|
||||
# Produce a static and a dynamic binary, and a HTML man page
|
||||
(
|
||||
cd "$compile_dir" || exit 1
|
||||
./configure
|
||||
make
|
||||
"$compile_cmd" -O2 -do_strip
|
||||
cp "$compile_result" "../$bintarget_dynamic"
|
||||
if test -n "$compile_static_opts"
|
||||
then
|
||||
"$compile_cmd" $compile_static_opts -O2 -do_strip
|
||||
cp "$compile_result" "../$bintarget_static"
|
||||
fi
|
||||
"$man_to_html_cmd"
|
||||
mv "$man_page_html" ..
|
||||
)
|
||||
|
||||
# Remove the build area
|
||||
# Disable this for debugging the merge process
|
||||
rm -rf "$target"
|
||||
|
||||
# Show the result
|
||||
./"$bintarget_dynamic" -version
|
||||
./"$bintarget_static" -version
|
||||
ls -l "$cdrskin_tarball"
|
||||
ls -l "$bintarget_dynamic"
|
||||
ls -l "$bintarget_static"
|
||||
ls -l $(basename "$man_page_html")
|
||||
|
@ -20,26 +20,30 @@ set -x
|
||||
# The script is to be run in the directory above the toplevel
|
||||
# directory of libburn resp. cdrskin development.
|
||||
#
|
||||
# libburn version used: http://libburn.pykix.org
|
||||
|
||||
# The top level directory in the SVN snapshot is named
|
||||
intermediate="./libburn_pykix"
|
||||
|
||||
# libburn source used: http://libburnia-project.org
|
||||
# Downloaded by:
|
||||
# $ svn co http://libburn-svn.pykix.org/trunk libburn_pykix
|
||||
# $ svn co http://libburnia-project.org/libburn/tags/... $intermediate
|
||||
# packed up in a tarball just to save it from inadverted changes by
|
||||
# $ tar czf libburn_svn.tgz libburn_pykix
|
||||
# $ tar czf libburn_svn.tgz $intermediate
|
||||
original="./libburn_svn.tgz"
|
||||
# Historic moments:
|
||||
# original="./libburn_svn_A60815.tgz"
|
||||
# original="./libburn_cdrskin_A60819.tgz"
|
||||
|
||||
# The top level directory in that snapshot is named
|
||||
intermediate="./libburn_pykix"
|
||||
|
||||
# My changes are in libburn-0.2.3.ts.develop , mainly in ./cdrskin
|
||||
# My changes are in $changes , mainly in $changes/cdrskin
|
||||
changes="./libburn-develop"
|
||||
|
||||
changes="./libburn-0.2.3.ts.develop"
|
||||
skin_rev="0.2.4"
|
||||
skin_release="1.1.1"
|
||||
patch_level=""
|
||||
skin_rev="$skin_release""$patch_level"
|
||||
|
||||
# The result directory and the name of the result tarballs
|
||||
target="./cdrskin-${skin_rev}"
|
||||
target="./cdrskin-${skin_release}"
|
||||
cdrskin_tarball="./cdrskin-${skin_rev}.tar.gz"
|
||||
cdrskin_tarball_svn="./cdrskin-${skin_rev}.svn.tar.gz"
|
||||
|
||||
@ -51,7 +55,10 @@ compile_cmd="./cdrskin/compile_cdrskin.sh"
|
||||
compile_static_opts="-static"
|
||||
compile_result="cdrskin/cdrskin"
|
||||
|
||||
bintarget_dynamic="cdrskin_${skin_rev}-x86-suse9_0"
|
||||
man_to_html_cmd="./cdrskin/convert_man_to_html.sh"
|
||||
man_page_html="cdrskin/man_1_cdrskin.html"
|
||||
|
||||
bintarget_dynamic="cdrskin_${skin_rev}-amd64-suse10_2"
|
||||
bintarget_static="$bintarget_dynamic"-static
|
||||
|
||||
if test -d "$changes"
|
||||
@ -107,7 +114,9 @@ then
|
||||
fi
|
||||
cp -a "$cdrskin_dir" "$cdrskin_target"
|
||||
|
||||
# Remove copied binaries
|
||||
# Remove copied vim.swp and binaries
|
||||
rm "$cdrskin_target"/.*.swp
|
||||
rm "$cdrskin_target"/.*.swo
|
||||
rm "$cdrskin_target"/*.o
|
||||
rm "$cdrskin_target"/cdrfifo
|
||||
rm "$cdrskin_target"/cdrskin
|
||||
@ -119,6 +128,8 @@ do
|
||||
rm "$cdrskin_target"/cdrskin_"$i"
|
||||
fi
|
||||
done
|
||||
|
||||
# Remove eventual SVN stuff from cdrskin directory
|
||||
for i in .deps .dirstamp .libs
|
||||
do
|
||||
if test -e "$cdrskin_target"/"$i"
|
||||
@ -127,6 +138,26 @@ do
|
||||
fi
|
||||
done
|
||||
|
||||
# Remove GIFs of cdrskin_eng.html
|
||||
rm "$cdrskin_target"/doener_*.gif "$cdrskin_target"/doener_*.png
|
||||
|
||||
# Remove automatically generated HTML man page
|
||||
rm "$cdrskin_target"/man_1_cdrskin.html
|
||||
|
||||
# Remove libcevap
|
||||
rm -rf "$target"/libcevap
|
||||
|
||||
# Remove all add_ts_changes_to_libburn besides this one
|
||||
for i in "$cdrskin_target"/add_ts_changes_to_libburn*
|
||||
do
|
||||
if test $(basename "$0") = $(basename "$i")
|
||||
then
|
||||
dummy=dummy
|
||||
else
|
||||
rm $i
|
||||
fi
|
||||
done
|
||||
|
||||
# Remove unwanted SVN stuff (TODO: avoid downloading it)
|
||||
for i in "$target"/.svn "$target"/*/.svn
|
||||
do
|
||||
@ -141,12 +172,6 @@ do
|
||||
fi
|
||||
done
|
||||
|
||||
## No more : Add own libburn-README in toplevel
|
||||
# cp -a "$changes"/README "$target"
|
||||
|
||||
## No more : Add modified Makefile.am
|
||||
# cp -a "$changes"/Makefile.am "$target"
|
||||
|
||||
|
||||
# Make SVN state tarball for the libburn team
|
||||
tar czf "$cdrskin_tarball_svn" "$target"
|
||||
@ -172,22 +197,39 @@ do
|
||||
fi
|
||||
done
|
||||
|
||||
# Repair non-portable shell code output of ./bootstrap
|
||||
(
|
||||
cd "$compile_dir" || exit 1
|
||||
sed -e 's/^for ac_header in$/test -z 1 \&\& for ac_header in dummy/' \
|
||||
< ./configure > ./configure-repaired
|
||||
if test "$?" = 0
|
||||
then
|
||||
echo "$0: Empty 'for ac_header in' found in configure." >&2
|
||||
fi
|
||||
mv ./configure-repaired ./configure
|
||||
chmod a+rx,go-w,u+w ./configure
|
||||
)
|
||||
|
||||
|
||||
# Pack it up to the new libburn+cdrskin-tarball
|
||||
tar czf "$cdrskin_tarball" "$target"
|
||||
|
||||
# Produce a static and a dynamic binary
|
||||
# Produce a static and a dynamic binary, and a HTML man page
|
||||
(
|
||||
cd "$compile_dir" || exit 1
|
||||
./configure
|
||||
make
|
||||
$compile_cmd -do_strip
|
||||
"$compile_cmd" -libburn_svn -O2 -do_strip
|
||||
cp "$compile_result" "../$bintarget_dynamic"
|
||||
if test -n "$compile_static_opts"
|
||||
then
|
||||
$compile_cmd $compile_static_opts -do_strip
|
||||
"$compile_cmd" $compile_static_opts -libburn_svn -O2 -do_strip
|
||||
cp "$compile_result" "../$bintarget_static"
|
||||
fi
|
||||
# "$compile_cmd" -libburn_svn -O2 -do_diet -do_strip
|
||||
# cp "$compile_result" "../$bintarget_dynamic"_diet
|
||||
"$man_to_html_cmd"
|
||||
mv "$man_page_html" ..
|
||||
)
|
||||
|
||||
# Remove the build area
|
||||
@ -200,4 +242,5 @@ rm -rf "$target"
|
||||
ls -l "$cdrskin_tarball"
|
||||
ls -l "$bintarget_dynamic"
|
||||
ls -l "$bintarget_static"
|
||||
ls -l $(basename "$man_page_html")
|
||||
|
@ -25,11 +25,16 @@
|
||||
#include <sys/time.h>
|
||||
#include <sys/select.h>
|
||||
|
||||
#ifndef Cdrfifo_standalonE
|
||||
/* <<< until release of 0.7.4 : for Libburn_has_open_trac_srC */
|
||||
#include "../libburn/libburn.h"
|
||||
#endif
|
||||
|
||||
#include "cdrfifo.h"
|
||||
|
||||
|
||||
/* Macro for creation of arrays of objects (or single objects) */
|
||||
#define TSOB_FELD(typ,anz) (typ *) malloc((anz)*sizeof(typ));
|
||||
#define TSOB_FELD(typ,anz) (typ *) calloc(anz, sizeof(typ));
|
||||
|
||||
|
||||
#define Cdrfifo_buffer_chunK 2048
|
||||
@ -38,7 +43,9 @@
|
||||
#define Cdrfifo_ffd_maX 100
|
||||
|
||||
|
||||
/* 1= enable , 0= disable status messages to stderr */
|
||||
/* 1= enable , 0= disable status messages to stderr
|
||||
2= report each
|
||||
*/
|
||||
static int Cdrfifo_debuG= 0;
|
||||
|
||||
|
||||
@ -48,6 +55,9 @@ struct CdrfifO {
|
||||
int source_fd;
|
||||
double in_counter;
|
||||
|
||||
double fd_in_counter;
|
||||
double fd_in_limit;
|
||||
|
||||
char *buffer;
|
||||
int buffer_size;
|
||||
int buffer_is_full;
|
||||
@ -72,20 +82,38 @@ struct CdrfifO {
|
||||
double empty_counter;
|
||||
double full_counter;
|
||||
|
||||
/* eventual ISO-9660 image size obtained from first 64k of input */
|
||||
double iso_fs_size;
|
||||
char *iso_fs_descr; /* eventually block 16 to 31 of input */
|
||||
|
||||
/* (sequential) fd chaining */
|
||||
/* fds: 0=source, 1=dest */
|
||||
int follow_up_fds[Cdrfifo_ffd_maX][2];
|
||||
|
||||
/* index of first byte in buffer which does not belong to predecessor fd */
|
||||
int follow_up_eop[Cdrfifo_ffd_maX];
|
||||
/* if follow_up_eop[i]==buffer_size : read_idx was 0 when this was set */
|
||||
int follow_up_was_full_buffer[Cdrfifo_ffd_maX];
|
||||
|
||||
/* index of first byte in buffer which belongs to [this] fd pair */
|
||||
int follow_up_sod[Cdrfifo_ffd_maX];
|
||||
|
||||
/* values for fd_in_limit */
|
||||
double follow_up_in_limits[Cdrfifo_ffd_maX];
|
||||
|
||||
/* number of defined follow-ups */
|
||||
int follow_up_fd_counter;
|
||||
|
||||
/* index of currently active (i.e. reading) follow-up */
|
||||
int follow_up_fd_idx;
|
||||
|
||||
|
||||
/* (simultaneous) peer chaining */
|
||||
struct CdrfifO *next;
|
||||
struct CdrfifO *prev;
|
||||
|
||||
/* rank in peer chain */
|
||||
int chain_idx;
|
||||
};
|
||||
|
||||
|
||||
@ -97,7 +125,7 @@ struct CdrfifO {
|
||||
struct burn_source object.
|
||||
@param chunk_size Size of buffer block for a single transaction (0=default)
|
||||
@param buffer_size Size of fifo buffer
|
||||
@param flag Unused yet
|
||||
@param flag bit0= Debugging verbosity
|
||||
@return 1 on success, <=0 on failure
|
||||
*/
|
||||
int Cdrfifo_new(struct CdrfifO **ff, int source_fd, int dest_fd,
|
||||
@ -117,6 +145,8 @@ int Cdrfifo_new(struct CdrfifO **ff, int source_fd, int dest_fd,
|
||||
buffer_size+= chunk_size-(buffer_size%chunk_size);
|
||||
o->source_fd= source_fd;
|
||||
o->in_counter= 0.0;
|
||||
o->fd_in_counter= 0;
|
||||
o->fd_in_limit= -1.0;
|
||||
o->buffer= NULL;
|
||||
o->buffer_is_full= 0;
|
||||
o->buffer_size= buffer_size;
|
||||
@ -137,14 +167,25 @@ int Cdrfifo_new(struct CdrfifO **ff, int source_fd, int dest_fd,
|
||||
o->get_counter= 0.0;
|
||||
o->empty_counter= 0.0;
|
||||
o->full_counter= 0.0;
|
||||
o->iso_fs_size= -1.0;
|
||||
o->iso_fs_descr= NULL;
|
||||
for(i= 0; i<Cdrfifo_ffd_maX; i++) {
|
||||
o->follow_up_fds[i][0]= o->follow_up_fds[i][1]= -1;
|
||||
o->follow_up_eop[i]= o->follow_up_sod[i]= -1;
|
||||
o->follow_up_was_full_buffer[i]= 0;
|
||||
o->follow_up_in_limits[i]= -1.0;
|
||||
}
|
||||
o->follow_up_fd_counter= 0;
|
||||
o->follow_up_fd_idx= -1;
|
||||
o->next= o->prev= NULL;
|
||||
o->chain_idx= 0;
|
||||
|
||||
#ifdef Libburn_has_open_trac_srC
|
||||
o->buffer= burn_os_alloc_buffer((size_t) buffer_size, 0);
|
||||
#else
|
||||
o->buffer= TSOB_FELD(char,buffer_size);
|
||||
#endif /* ! Libburn_has_open_trac_srC */
|
||||
|
||||
if(o->buffer==NULL)
|
||||
goto failed;
|
||||
return(1);
|
||||
@ -162,10 +203,11 @@ int Cdrfifo_close(struct CdrfifO *o, int flag)
|
||||
if(o->dest_fd!=-1)
|
||||
close(o->dest_fd);
|
||||
o->dest_fd= -1;
|
||||
for(i=0; i<o->follow_up_fd_counter; i++)
|
||||
for(i=0; i<o->follow_up_fd_counter; i++) {
|
||||
if(o->follow_up_fds[i][1]!=-1)
|
||||
close(o->follow_up_fds[i][1]);
|
||||
o->follow_up_fds[i][1]= -1;
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
@ -194,8 +236,16 @@ 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)
|
||||
#ifdef Libburn_has_open_trac_srC
|
||||
burn_os_free_buffer(o->buffer, o->buffer_size, 0);
|
||||
#else
|
||||
free((char *) o->buffer);
|
||||
#endif /* Libburn_has_open_trac_srC */
|
||||
|
||||
free((char *) o);
|
||||
(*ff)= NULL;
|
||||
return(1);
|
||||
@ -224,6 +274,26 @@ int Cdrfifo_set_speed_limit(struct CdrfifO *o, double bytes_per_second,
|
||||
}
|
||||
|
||||
|
||||
/** Set a fixed size for input in order to cut off any unwanted tail
|
||||
@param o The fifo object
|
||||
@param idx index for fds attached via Cdrfifo_attach_follow_up_fds(),
|
||||
first attached is 0, <0 directs limit to active fd limit
|
||||
(i.e. first track is -1, second track is 0, third is 1, ...)
|
||||
*/
|
||||
int Cdrfifo_set_fd_in_limit(struct CdrfifO *o, double fd_in_limit, int idx,
|
||||
int flag)
|
||||
{
|
||||
if(idx<0) {
|
||||
o->fd_in_limit= fd_in_limit;
|
||||
return(1);
|
||||
}
|
||||
if(idx >= o->follow_up_fd_counter)
|
||||
return(0);
|
||||
o->follow_up_in_limits[idx]= fd_in_limit;
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
int Cdrfifo_set_fds(struct CdrfifO *o, int source_fd, int dest_fd, int flag)
|
||||
{
|
||||
o->source_fd= source_fd;
|
||||
@ -244,6 +314,7 @@ int Cdrfifo_get_fds(struct CdrfifO *o, int *source_fd, int *dest_fd, int flag)
|
||||
fifo buffer when its predecessors are exhausted. Reading will start as
|
||||
soon as reading of the predecessor encounters EOF. Writing will start
|
||||
as soon as all pending predecessor data are written.
|
||||
@return index number of new item + 1, <=0 indicates error
|
||||
*/
|
||||
int Cdrfifo_attach_follow_up_fds(struct CdrfifO *o, int source_fd, int dest_fd,
|
||||
int flag)
|
||||
@ -253,7 +324,7 @@ int Cdrfifo_attach_follow_up_fds(struct CdrfifO *o, int source_fd, int dest_fd,
|
||||
o->follow_up_fds[o->follow_up_fd_counter][0]= source_fd;
|
||||
o->follow_up_fds[o->follow_up_fd_counter][1]= dest_fd;
|
||||
o->follow_up_fd_counter++;
|
||||
return(1);
|
||||
return(o->follow_up_fd_counter);
|
||||
}
|
||||
|
||||
|
||||
@ -262,10 +333,16 @@ int Cdrfifo_attach_follow_up_fds(struct CdrfifO *o, int source_fd, int dest_fd,
|
||||
*/
|
||||
int Cdrfifo_attach_peer(struct CdrfifO *o, struct CdrfifO *next, int flag)
|
||||
{
|
||||
int idx;
|
||||
struct CdrfifO *s;
|
||||
|
||||
for(s= o;s->prev!=NULL;s= s->prev); /* determine start of o-chain */
|
||||
for(;o->next!=NULL;o= o->next); /* determine end of o-chain */
|
||||
for(;next->prev!=NULL;next= next->prev); /* determine start of next-chain */
|
||||
next->prev= o;
|
||||
o->next= next;
|
||||
for(idx= 0;s!=NULL;s= s->next)
|
||||
s->chain_idx= idx++;
|
||||
return(1);
|
||||
}
|
||||
|
||||
@ -338,6 +415,21 @@ int Cdrfifo_get_min_fill(struct CdrfifO *o, int *total_min_fill,
|
||||
}
|
||||
|
||||
|
||||
int Cdrfifo_get_iso_fs_size(struct CdrfifO *o, double *size_in_bytes, int flag)
|
||||
{
|
||||
*size_in_bytes= o->iso_fs_size;
|
||||
return(o->iso_fs_size>=2048);
|
||||
}
|
||||
|
||||
|
||||
int Cdrfifo_adopt_iso_fs_descr(struct CdrfifO *o, char **pt, int flag)
|
||||
{
|
||||
*pt= o->iso_fs_descr;
|
||||
o->iso_fs_descr= NULL;
|
||||
return(*pt!=NULL);
|
||||
}
|
||||
|
||||
|
||||
/** Get counters which are mentioned by cdrecord at the end of burning.
|
||||
It still has to be examined wether they mean what i believe they do.
|
||||
*/
|
||||
@ -346,7 +438,7 @@ int Cdrfifo_get_cdr_counters(struct CdrfifO *o,
|
||||
double *empty_counter, double *full_counter,
|
||||
int flag)
|
||||
{
|
||||
*put_counter= o->put_counter;;
|
||||
*put_counter= o->put_counter;
|
||||
*get_counter= o->get_counter;
|
||||
*empty_counter= o->empty_counter;
|
||||
*full_counter= o->full_counter;
|
||||
@ -371,10 +463,26 @@ int Cdrfifo_eop_adjust(struct CdrfifO *o,int *buffer_fill, int *eop_idx,
|
||||
for(i=0; i<=o->follow_up_fd_idx; i++) {
|
||||
if(o->follow_up_eop[i]>=0 && o->follow_up_eop[i]>=o->read_idx) {
|
||||
eop_is_near= 1;
|
||||
valid_fill= o->follow_up_eop[i]-o->read_idx;
|
||||
if(o->follow_up_eop[i]<o->buffer_size || o->read_idx>0) {
|
||||
valid_fill= o->follow_up_eop[i]-o->read_idx;
|
||||
o->follow_up_was_full_buffer[i]= 0;
|
||||
} else {
|
||||
/*
|
||||
If an input fd change hit exactly the buffer end then follow_up_eop
|
||||
points to buffer_size and not to 0. So it is time to switch output
|
||||
pipes unless this is immediately after follow_up_eop was set and
|
||||
read_idx was 0 (... if this is possible at all while write_idx is 0).
|
||||
follow_up_was_full_buffer was set in this case and gets invalid as
|
||||
soon as a non-0 read_idx is detected (see above).
|
||||
*/
|
||||
if(o->follow_up_was_full_buffer[i])
|
||||
valid_fill= o->buffer_size;
|
||||
else
|
||||
valid_fill= 0; /* the current pipe is completely served */
|
||||
}
|
||||
if(valid_fill==0)
|
||||
*eop_idx= i;
|
||||
else if(valid_fill<=o->chunk_size)
|
||||
else if(valid_fill<o->chunk_size)
|
||||
eop_is_near= 2; /* for debugging. to carry a break point */
|
||||
break;
|
||||
}
|
||||
@ -399,7 +507,7 @@ static int Cdrfifo_setup_try(struct CdrfifO *o, struct timeval start_tv,
|
||||
*/
|
||||
{
|
||||
int buffer_space,buffer_fill,eop_reached= -1,eop_is_near= 0,was_closed;
|
||||
int fd_buffer_fill;
|
||||
int fd_buffer_fill, eop_reached_counter= 0;
|
||||
struct timeval current_tv;
|
||||
struct timezone tz;
|
||||
double diff_time,diff_counter,limit,min_wait_time;
|
||||
@ -428,21 +536,26 @@ setup_try:;
|
||||
|
||||
if(eop_reached>=0) { /* switch to next output fd */
|
||||
o->dest_fd= o->follow_up_fds[eop_reached][1];
|
||||
if(Cdrfifo_debuG)
|
||||
fprintf(stderr,"\ncdrfifo %d: new fifo destination fd : %d\n",
|
||||
o->chain_idx,o->dest_fd);
|
||||
o->read_idx= o->follow_up_sod[eop_reached];
|
||||
o->follow_up_eop[eop_reached]= -1;
|
||||
eop_is_near= 0;
|
||||
eop_reached= -1;
|
||||
eop_reached_counter= 0;
|
||||
goto setup_try;
|
||||
} else {
|
||||
/* work is really done */
|
||||
if((!was_closed) && ((flag&1)||Cdrfifo_debuG))
|
||||
fprintf(stderr,
|
||||
"\ncdrfifo_debug: w=%d r=%d | b=%d s=%d | i=%.f o=%.f (done)\n",
|
||||
o->write_idx,o->read_idx,buffer_fill,buffer_space,
|
||||
"\ncdrfifo %d: w=%d r=%d | b=%d s=%d | i=%.f o=%.f (done)\n",
|
||||
o->chain_idx,o->write_idx,o->read_idx,buffer_fill,buffer_space,
|
||||
o->in_counter,o->out_counter);
|
||||
return(2);
|
||||
}
|
||||
}
|
||||
} else if(eop_reached>=0)
|
||||
eop_reached_counter++;
|
||||
if(o->interval_counter>0) {
|
||||
if(o->total_min_fill>buffer_fill && o->source_fd>=0)
|
||||
o->total_min_fill= buffer_fill;
|
||||
@ -521,7 +634,7 @@ return: <0 = error , 0 = idle , 1 = did some work
|
||||
*/
|
||||
{
|
||||
double buffer_space;
|
||||
int can_read,can_write,ret,did_work= 0,idx,sod,eop_is_near,eop_idx;
|
||||
int can_read,can_write= 0,ret,did_work= 0,idx,sod,eop_is_near,eop_idx;
|
||||
|
||||
buffer_space= Cdrfifo_tell_buffer_space(o,0);
|
||||
if(o->dest_fd>=0) if(FD_ISSET((o->dest_fd),wts)) {
|
||||
@ -544,7 +657,8 @@ return: <0 = error , 0 = idle , 1 = did some work
|
||||
if(ret==-1) {
|
||||
|
||||
/* >>> handle broken pipe */;
|
||||
fprintf(stderr,"\ncdrfifo: on write: errno=%d , \"%s\"\n",errno,
|
||||
fprintf(stderr,"\ncdrfifo %d: on write: errno=%d , \"%s\"\n",
|
||||
o->chain_idx,errno,
|
||||
errno==0?"-no error code available-":strerror(errno));
|
||||
|
||||
if(!(flag&4))
|
||||
@ -563,30 +677,87 @@ return: <0 = error , 0 = idle , 1 = did some work
|
||||
after_write:;
|
||||
if(o->source_fd>=0) if(FD_ISSET((o->source_fd),rds)) {
|
||||
can_read= o->buffer_size - o->write_idx;
|
||||
|
||||
#ifdef Libburn_has_open_trac_srC
|
||||
|
||||
/* ts A91115
|
||||
This chunksize must be aligned to filesystem blocksize.
|
||||
*/
|
||||
#define Cdrfifo_o_direct_chunK 32768
|
||||
|
||||
if(o->write_idx < o->read_idx && o->write_idx + can_read > o->read_idx)
|
||||
can_read= o->read_idx - o->write_idx;
|
||||
if(o->fd_in_limit>=0.0)
|
||||
if(can_read > o->fd_in_limit - o->fd_in_counter)
|
||||
can_read= o->fd_in_limit - o->fd_in_counter;
|
||||
/* Make sure to read with properly aligned size */
|
||||
if(can_read > Cdrfifo_o_direct_chunK)
|
||||
can_read= Cdrfifo_o_direct_chunK;
|
||||
else if(can_read < Cdrfifo_o_direct_chunK)
|
||||
can_read= -1;
|
||||
ret= 0;
|
||||
if(can_read>0)
|
||||
ret= read(o->source_fd,o->buffer+o->write_idx,can_read);
|
||||
if(can_read < 0) {
|
||||
/* waiting for a full Cdrfifo_o_direct_chunK to fit */
|
||||
if(can_write <= 0 && o->dest_fd >= 0) {
|
||||
fd_set rds,wts,exs;
|
||||
struct timeval wt;
|
||||
|
||||
FD_ZERO(&rds);
|
||||
FD_ZERO(&wts);
|
||||
FD_ZERO(&exs);
|
||||
FD_SET((o->dest_fd),&wts);
|
||||
wt.tv_sec= 0;
|
||||
wt.tv_usec= 10000;
|
||||
select(o->dest_fd + 1,&rds, &wts, &exs, &wt);
|
||||
|
||||
}
|
||||
} else
|
||||
|
||||
#else /* Libburn_has_open_trac_srC */
|
||||
|
||||
if(can_read>o->chunk_size)
|
||||
can_read= o->chunk_size;
|
||||
if(o->write_idx<o->read_idx && o->write_idx+can_read > o->read_idx)
|
||||
can_read= o->read_idx - o->write_idx;
|
||||
ret= read(o->source_fd,o->buffer+o->write_idx,can_read);
|
||||
if(o->fd_in_limit>=0.0)
|
||||
if(can_read > o->fd_in_limit - o->fd_in_counter)
|
||||
can_read= o->fd_in_limit - o->fd_in_counter;
|
||||
ret= 0;
|
||||
if(can_read>0)
|
||||
ret= read(o->source_fd,o->buffer+o->write_idx,can_read);
|
||||
|
||||
#endif /* ! Libburn_has_open_trac_srC */
|
||||
|
||||
if(ret==-1) {
|
||||
|
||||
/* >>> handle input error */;
|
||||
fprintf(stderr,"\ncdrfifo: on read: errno=%d , \"%s\"\n",errno,
|
||||
fprintf(stderr,"\ncdrfifo %d: on read: errno=%d , \"%s\"\n",
|
||||
o->chain_idx,errno,
|
||||
errno==0?"-no error code available-":strerror(errno));
|
||||
|
||||
o->source_fd= -1;
|
||||
} else if(ret==0) { /* eof */
|
||||
/* activate eventual follow-up source fd */
|
||||
if(Cdrfifo_debuG || (flag&1))
|
||||
fprintf(stderr,"\ncdrfifo: on read(%d,buffer,%d): eof\n",
|
||||
o->source_fd,can_read);
|
||||
fprintf(stderr,"\ncdrfifo %d: on read(%d,buffer,%d): eof\n",
|
||||
o->chain_idx,o->source_fd,can_read);
|
||||
if(o->follow_up_fd_idx+1 < o->follow_up_fd_counter) {
|
||||
idx= ++(o->follow_up_fd_idx);
|
||||
o->source_fd= o->follow_up_fds[idx][0];
|
||||
/* End-Of-Previous */
|
||||
if(o->write_idx==0)
|
||||
if(o->write_idx==0) {
|
||||
o->follow_up_eop[idx]= o->buffer_size;
|
||||
else
|
||||
|
||||
/* A70304 : can this happen ? */
|
||||
o->follow_up_was_full_buffer[idx]= (o->read_idx==0);
|
||||
|
||||
if(Cdrfifo_debuG || (flag&1))
|
||||
fprintf(stderr,"\ncdrfifo %d: write_idx 0 on eop: read_idx= %d\n",
|
||||
o->chain_idx,o->read_idx);
|
||||
|
||||
} else
|
||||
o->follow_up_eop[idx]= o->write_idx;
|
||||
/* Start-Of-Data . Try to start at next full chunk */
|
||||
sod= o->write_idx;
|
||||
@ -599,8 +770,11 @@ after_write:;
|
||||
sod= 0;
|
||||
o->follow_up_sod[idx]= sod;
|
||||
o->write_idx= sod;
|
||||
o->fd_in_counter= 0;
|
||||
o->fd_in_limit= o->follow_up_in_limits[idx];
|
||||
if(Cdrfifo_debuG || (flag&1))
|
||||
fprintf(stderr,"\ncdrfio: new fifo source fd : %d\n",o->source_fd);
|
||||
fprintf(stderr,"\ncdrfifo %d: new fifo source fd : %d\n",
|
||||
o->chain_idx,o->source_fd);
|
||||
} else {
|
||||
o->source_fd= -1;
|
||||
}
|
||||
@ -608,6 +782,7 @@ after_write:;
|
||||
did_work= 1;
|
||||
o->put_counter++;
|
||||
o->in_counter+= ret;
|
||||
o->fd_in_counter+= ret;
|
||||
o->write_idx+= ret;
|
||||
if(o->write_idx>=o->buffer_size)
|
||||
o->write_idx= 0;
|
||||
@ -732,13 +907,13 @@ ex:;
|
||||
} else
|
||||
elapsed= wait_usec;
|
||||
if(elapsed>=wait_usec) {
|
||||
if((flag&1)||Cdrfifo_debuG) {
|
||||
if((flag&1)||Cdrfifo_debuG>=2) {
|
||||
fprintf(stderr,"\n");
|
||||
for(ff= o; ff!=NULL; ff= ff->next) {
|
||||
buffer_space= Cdrfifo_tell_buffer_space(ff,0);
|
||||
fprintf(stderr,
|
||||
"cdrfifo_debug: w=%d r=%d | b=%d s=%d | i=%.f o=%.f\n",
|
||||
ff->write_idx,ff->read_idx,
|
||||
"cdrfifo %d: w=%d r=%d | b=%d s=%d | i=%.f o=%.f\n",
|
||||
ff->chain_idx,ff->write_idx,ff->read_idx,
|
||||
ff->buffer_size-buffer_space,buffer_space,
|
||||
ff->in_counter,ff->out_counter);
|
||||
}
|
||||
@ -751,7 +926,7 @@ ex:;
|
||||
|
||||
|
||||
/** Fill the fifo as far as possible without writing to destination fd */
|
||||
int Cdrfifo_fill(struct CdrfifO *o, int flag)
|
||||
int Cdrfifo_fill(struct CdrfifO *o, int size, int flag)
|
||||
{
|
||||
int ret,fill= 0,space,state;
|
||||
|
||||
@ -765,6 +940,8 @@ int Cdrfifo_fill(struct CdrfifO *o, int flag)
|
||||
} else if(state!=1)
|
||||
break;
|
||||
if(space<=0)
|
||||
break;
|
||||
if(size>=0 && fill>=size)
|
||||
break;
|
||||
ret= Cdrfifo_try_to_work(o,100000,NULL,NULL,2);
|
||||
if(ret<0) {
|
||||
@ -776,6 +953,29 @@ int Cdrfifo_fill(struct CdrfifO *o, int flag)
|
||||
if(ret==2)
|
||||
break;
|
||||
}
|
||||
|
||||
#ifndef Cdrfifo_standalonE
|
||||
if(fill>=32*2048) {
|
||||
int Scan_for_iso_size(unsigned char data[2048], double *size_in_bytes,
|
||||
int flag);
|
||||
int bs= 16*2048;
|
||||
double size;
|
||||
|
||||
/* memorize blocks 16 to 31 */
|
||||
if(o->iso_fs_descr!=NULL)
|
||||
free((char *) o->iso_fs_descr);
|
||||
o->iso_fs_descr= TSOB_FELD(char,bs);
|
||||
if(o->iso_fs_descr==NULL)
|
||||
return(-1);
|
||||
memcpy(o->iso_fs_descr,o->buffer+bs,bs);
|
||||
|
||||
/* try to obtain ISO-9660 file system size from block 16 */
|
||||
ret= Scan_for_iso_size((unsigned char *) (o->buffer+bs), &size, 0);
|
||||
if(ret>0)
|
||||
o->iso_fs_size= size;
|
||||
}
|
||||
#endif
|
||||
|
||||
o->total_min_fill= fill;
|
||||
o->interval_min_fill= fill;
|
||||
return(1);
|
||||
@ -828,6 +1028,76 @@ double Scanf_io_size(char *text, int flag)
|
||||
}
|
||||
|
||||
|
||||
/* This is a hardcoded test mock-up for two simultaneous fifos of which the
|
||||
one runs with block size 2048 and feeds the other which runs with 2352.
|
||||
Both fifos have the same number of follow_up pipes (tracks) which shall
|
||||
be connected 1-to-1.
|
||||
*/
|
||||
int Test_mixed_bs(char **paths, int path_count,
|
||||
int fs_size, double speed_limit, double interval, int flag)
|
||||
/*
|
||||
bit0= debugging verbousity
|
||||
*/
|
||||
{
|
||||
int fd_in[100],fd_out[100],ret,pipe_fds[100][2],real_out[100];
|
||||
int i,iv,stall_counter= 0,cycle_counter= 0.0;
|
||||
char buf[10240], target_path[80];
|
||||
double in_counter, out_counter, prev_in= -1.0, prev_out= -1.0;
|
||||
struct CdrfifO *ff_in= NULL, *ff_out= NULL;
|
||||
|
||||
if(path_count<1)
|
||||
return(2);
|
||||
Cdrfifo_new(&ff_in,fd_in[0],fd_out[0],2048,fs_size,0);
|
||||
for(i= 0; i<path_count; i++) {
|
||||
fd_in[2*i]= open(paths[i],O_RDONLY);
|
||||
if(fd_in[2*i]==-1)
|
||||
return(0);
|
||||
if(pipe(pipe_fds[2*i])==-1)
|
||||
return(-1);
|
||||
fd_out[2*i]= pipe_fds[2*i][1];
|
||||
if(i==0)
|
||||
ret= Cdrfifo_new(&ff_in,fd_in[2*i],fd_out[2*i],2048,fs_size,0);
|
||||
else
|
||||
ret= Cdrfifo_attach_follow_up_fds(ff_in,fd_in[2*i],fd_out[2*i],0);
|
||||
if(ret<=0)
|
||||
return(ret);
|
||||
fd_in[2*i+1]= pipe_fds[2*i][0];
|
||||
sprintf(target_path,"/dvdbuffer/fifo_mixed_bs_test_%d",i);
|
||||
fd_out[2*i+1]= open(target_path,O_WRONLY|O_CREAT|O_TRUNC, S_IRUSR|S_IWUSR);
|
||||
if(i==0)
|
||||
ret= Cdrfifo_new(&ff_out,fd_in[2*i+1],fd_out[2*i+1],2352,fs_size,0);
|
||||
else
|
||||
ret= Cdrfifo_attach_follow_up_fds(ff_out,fd_in[2*i+1],fd_out[2*i+1],0);
|
||||
if(ret<=0)
|
||||
return(ret);
|
||||
fprintf(stderr,"test_mixed_bs: %d : %2d fifo %2d pipe %2d fifo %2d : %s\n",
|
||||
i, fd_in[2*i],fd_out[2*i],fd_in[2*i+1],fd_out[2*i+1], target_path);
|
||||
}
|
||||
Cdrfifo_attach_peer(ff_in,ff_out,0);
|
||||
|
||||
|
||||
/* Let the fifos work */
|
||||
iv= interval*1e6;
|
||||
while(1) {
|
||||
ret= Cdrfifo_try_to_work(ff_in,iv,NULL,NULL,flag&1);
|
||||
if(ret<0 || ret==2) { /* <0 = error , 2 = work is done */
|
||||
fprintf(stderr,"\ncdrfifo %d: fifo ended work with ret=%d\n",
|
||||
ff_in->chain_idx,ret);
|
||||
if(ret<0)
|
||||
return(-7);
|
||||
break;
|
||||
}
|
||||
cycle_counter++;
|
||||
Cdrfifo_get_counters(ff_in, &in_counter, &out_counter, 0);
|
||||
if(prev_in == in_counter && prev_out == out_counter)
|
||||
stall_counter++;
|
||||
prev_in= in_counter;
|
||||
prev_out= out_counter;
|
||||
}
|
||||
return(1);
|
||||
}
|
||||
|
||||
|
||||
/* This is a hardcoded test mock-up for two simultaneous fifos of which the
|
||||
first one simulates the cdrskin fifo feeding libburn and the second one
|
||||
simulates libburn and the burner at given speed. Both have two fd pairs
|
||||
@ -886,7 +1156,8 @@ int Test_multi(int fs_size, double speed_limit, double interval, int flag)
|
||||
while(1) {
|
||||
ret= Cdrfifo_try_to_work(ff1,iv,NULL,NULL,flag&1);
|
||||
if(ret<0 || ret==2) { /* <0 = error , 2 = work is done */
|
||||
fprintf(stderr,"\ncdrfifo: fifo ended work with ret=%d\n",ret);
|
||||
fprintf(stderr,"\ncdrfifo %d: fifo ended work with ret=%d\n",
|
||||
ff1->chain_idx,ret);
|
||||
if(ret<0)
|
||||
return(-7);
|
||||
break;
|
||||
@ -945,6 +1216,13 @@ int main(int argc, char **argv)
|
||||
} else if(strncmp(argv[i],"vb=",3)==0) {
|
||||
sscanf(argv[i]+3,"%d",&verbous);
|
||||
|
||||
} else if(strcmp(argv[i],"-mixed_bs_test")==0) {
|
||||
|
||||
ret= Test_mixed_bs(argv+i+1,argc-i-1,
|
||||
(int) fs_value,speed_limit,interval,(verbous>=2));
|
||||
fprintf(stderr,"Test_mixed_bs(): ret= %d\n",ret);
|
||||
exit(ret<0);
|
||||
|
||||
} else if(strcmp(argv[i],"-multi_test")==0) {
|
||||
|
||||
if(speed_limit==0.0)
|
||||
@ -988,7 +1266,7 @@ int main(int argc, char **argv)
|
||||
if(speed_limit!=0.0)
|
||||
Cdrfifo_set_speed_limit(ff,speed_limit,0);
|
||||
if(fill_buffer) {
|
||||
ret= Cdrfifo_fill(ff,0);
|
||||
ret= Cdrfifo_fill(ff,0,0);
|
||||
if(ret<=0) {
|
||||
fprintf(stderr,
|
||||
"cdrfifo: FATAL : initial filling of fifo buffer failed\n");
|
||||
|
@ -15,7 +15,7 @@
|
||||
|
||||
|
||||
/** The fifo buffer which will smoothen the data stream from data provider
|
||||
to data consumer. Although this is not a mandatory lifesavier for modern
|
||||
to data consumer. Although this is not a mandatory lifesaver for modern
|
||||
burners any more, a fifo can speed up burning of data which is delivered
|
||||
with varying bandwidths (e.g. compressed archives created on the fly
|
||||
or mkisofs running at its speed limit.).
|
||||
@ -33,7 +33,7 @@ struct CdrfifO;
|
||||
struct burn_source object.
|
||||
@param chunk_size Size of buffer block for a single transaction (0=default)
|
||||
@param buffer_size Size of fifo buffer
|
||||
@param flag unused yet
|
||||
@param flag bit0= Debugging verbosity
|
||||
@return 1 on success, <=0 on failure
|
||||
*/
|
||||
int Cdrfifo_new(struct CdrfifO **ff, int source_fd, int dest_fd,
|
||||
@ -64,6 +64,16 @@ int Cdrfifo_get_sizes(struct CdrfifO *o, int *chunk_size, int *buffer_size,
|
||||
int Cdrfifo_set_speed_limit(struct CdrfifO *o, double bytes_per_second,
|
||||
int flag);
|
||||
|
||||
/** Set a fixed size for input in order to cut off any unwanted tail
|
||||
@param o The fifo object
|
||||
@param idx index for fds attached via Cdrfifo_attach_follow_up_fds(),
|
||||
first attached is 0, <0 directs limit to active fd limit
|
||||
(i.e. first track is -1, second track is 0, third is 1, ...)
|
||||
*/
|
||||
int Cdrfifo_set_fd_in_limit(struct CdrfifO *o, double fd_in_limit, int idx,
|
||||
int flag);
|
||||
|
||||
|
||||
int Cdrfifo_set_fds(struct CdrfifO *o, int source_fd, int dest_fd, int flag);
|
||||
int Cdrfifo_get_fds(struct CdrfifO *o, int *source_fd, int *dest_fd, int flag);
|
||||
|
||||
@ -72,6 +82,7 @@ int Cdrfifo_get_fds(struct CdrfifO *o, int *source_fd, int *dest_fd, int flag);
|
||||
fifo buffer when its predecessors are exhausted. Reading will start as
|
||||
soon as reading of the predecessor encounters EOF. Writing will start
|
||||
as soon as all pending predecessor data are written.
|
||||
@return index number of new item + 1, <=0 indicates error
|
||||
*/
|
||||
int Cdrfifo_attach_follow_up_fds(struct CdrfifO *o, int source_fd, int dest_fd,
|
||||
int flag);
|
||||
@ -106,6 +117,21 @@ int Cdrfifo_get_cdr_counters(struct CdrfifO *o,
|
||||
double *empty_counter, double *full_counter,
|
||||
int flag);
|
||||
|
||||
/** Inquire the eventually detected size of an eventual ISO-9660 file system
|
||||
@return 0=no ISO resp. size detected, 1=size_in_bytes is valid
|
||||
*/
|
||||
int Cdrfifo_get_iso_fs_size(struct CdrfifO *o, double *size_in_bytes,int flag);
|
||||
|
||||
|
||||
/** Take over the eventually memorized blocks 16 to 31 of input (2 kB each).
|
||||
The fifo forgets the blocks by this call. I.e. a second one will return 0.
|
||||
After this call it is the responsibility of the caller to dispose the
|
||||
retrieved memory via call free().
|
||||
@param pt Will be filled either with NULL or a pointer to 32 kB of data
|
||||
@return 0=nothing is buffered, 1=pt points to valid freeable data
|
||||
*/
|
||||
int Cdrfifo_adopt_iso_fs_descr(struct CdrfifO *o, char **pt, int flag);
|
||||
|
||||
|
||||
/** Check for pending data at the fifo's source file descriptor and wether the
|
||||
fifo is ready to take them. Simultaneously check the buffer for existing
|
||||
@ -134,10 +160,11 @@ int Cdrfifo_get_cdr_counters(struct CdrfifO *o,
|
||||
int Cdrfifo_try_to_work(struct CdrfifO *o, int wait_usec,
|
||||
char *reply_buffer, int *reply_count, int flag);
|
||||
|
||||
/** Fill the fifo as far as possible without writing to destination fd
|
||||
/** Fill the fifo as far as possible without writing to destination fd.
|
||||
@param size if >=0 : end filling after the given number of bytes
|
||||
@return 1 on success, <=0 on failure
|
||||
*/
|
||||
int Cdrfifo_fill(struct CdrfifO *o, int flag);
|
||||
int Cdrfifo_fill(struct CdrfifO *o, int size, int flag);
|
||||
|
||||
|
||||
#endif /* Cdrfifo_headerfile_includeD */
|
||||
|
1385
cdrskin/cdrskin.1
Normal file
1385
cdrskin/cdrskin.1
Normal file
File diff suppressed because it is too large
Load Diff
5656
cdrskin/cdrskin.c
5656
cdrskin/cdrskin.c
File diff suppressed because it is too large
Load Diff
@ -2,7 +2,7 @@
|
||||
|
||||
<HEAD>
|
||||
<META NAME="description" CONTENT="cdrskin, a limited cdrecord compatibility wrapper for libburn">
|
||||
<META NAME="keywords" CONTENT="cdrskin, libburn, burn, CD, linux, CDR, CD-R, CDRW, CD-RW, cdrecord, compatible, scdbackup, burning">
|
||||
<META NAME="keywords" CONTENT="cdrskin, libburn, libburnia, burn, CD, DVD, BD, linux, recording, burning, CD-R, CD-RW, DVD-R, DVD-R DL, DVD-RW, DVD+RW, DVD+R, DVD+R DL, DVD-RAM, BD-RE, BD-R, cdrecord, compatible, scdbackup">
|
||||
<META NAME="robots" CONTENT="follow">
|
||||
<TITLE>cdrskin homepage english</TITLE>
|
||||
</HEAD>
|
||||
@ -11,36 +11,50 @@
|
||||
<FONT SIZE=+1>
|
||||
|
||||
<CENTER>
|
||||
<P><H2>Homepage of</H2><H1><BR>cdrskin</H1><BR>
|
||||
<!-- <FONT SIZE=+0><A HREF="cdrskin_ger.html">deutsch (german)</A></FONT> -->
|
||||
<A HREF="http://en.wikipedia.org/wiki/D%C3%B6ner_kebab">
|
||||
<IMG SRC="doener_150x200_tr_octx.png" BORDER=0
|
||||
ALT="cdrskin logo: Doener mit Scharf">
|
||||
</A>
|
||||
<P><H2> Homepage of </H2>
|
||||
<H1> cdrskin </H1>
|
||||
|
||||
<H2>Limited cdrecord compatibility wrapper for libburn</H2>
|
||||
</CENTER>
|
||||
|
||||
<P>
|
||||
<H2>Purpose:</H2>
|
||||
<UL>
|
||||
<LI>Burns preformatted data to CD-R or CD-RW</LI>
|
||||
</UL>
|
||||
Burns preformatted data to CD, DVD, and BD media:<BR>
|
||||
CD-R, DVD-R, DVD-R DL, DVD+R, DVD+R DL, BD-R, CD-RW,
|
||||
DVD-RW, DVD-RAM, DVD+RW, BD-RE
|
||||
</P>
|
||||
<P>
|
||||
|
||||
<HR>
|
||||
|
||||
<A HREF="#download">Direct hop to download links -></A>
|
||||
|
||||
<P>
|
||||
<H2>Hardware requirements:</H2>
|
||||
A CD recorder suitable for
|
||||
<A HREF="http://libburn.pykix.org">libburn.pykix.org</A>
|
||||
(SCSI or IDE/ATAPI writers compliant to mmc standard).
|
||||
About any CD, DVD, or BD recorder produced in the recent ten years.
|
||||
<BR>
|
||||
<A HREF="http://libburnia-project.org">libburn</A>
|
||||
supports recorders which are compliant to standards MMC-1 for CD and
|
||||
MMC-5 for DVD or BD. Linux, FreeBSD, and Solaris allow to access drives
|
||||
connected via SCSI, PATA (aka IDE, ATA), USB, or SATA.
|
||||
<BR>
|
||||
</P>
|
||||
|
||||
<P>
|
||||
<H2>Software requirements :</H2>
|
||||
<DL>
|
||||
<DT>Linux kernel 2.4 or higher</DT>
|
||||
<DD>With kernel 2.4 the drive has to be under ide-scsi emulation.</DD>
|
||||
<DT>Linux with kernel 2.4 or higher (and libc, of course) :</DT>
|
||||
<DD>With kernel 2.4 an ATA drive has to be under ide-scsi emulation.</DD>
|
||||
<DD>With kernel 2.6 the drive should not be under ide-scsi.</DD>
|
||||
<DT>or FreeBSD (with libc, of course) :</DT>
|
||||
<DD>ATA and SATA drives need atapicam running.</DD>
|
||||
<DD>libcam has to be installed.</DD>
|
||||
<DT>or Solaris (with libc, of course) :</DT>
|
||||
<DD>Tested on kernel 5.11, hopefully suitable for older ones too.</DD>
|
||||
<DT>libpthread</DT>
|
||||
<DD>is supposed to be a standard system component.</DD>
|
||||
</DL>
|
||||
@ -51,14 +65,18 @@ A CD recorder suitable for
|
||||
GPL software included:<BR>
|
||||
</H2>
|
||||
<DL>
|
||||
<DT>libburn-0.2.3 stabilized SVN snapshot</DT>
|
||||
<DD>(by Derek Foreman, Ben Jansens, and team of libburn.pykix.org)</DD>
|
||||
<DD>transfers data to CD</DD>
|
||||
<DT>libburn-1.1.0</DT>
|
||||
<DD>(founded by Derek Foreman and Ben Jansens,
|
||||
developed and maintained since August 2006 by
|
||||
Thomas Schmitt from team of libburnia-project.org)
|
||||
</DD>
|
||||
<DD>transfers data to CD, DVD, BD</DD>
|
||||
</DL>
|
||||
</P>
|
||||
|
||||
<P>
|
||||
This program system has been tested on Intel/AMD Linux systems only.<BR>
|
||||
This program system has been tested on Intel/AMD with Linux, FreeBSD,
|
||||
and OpenSolaris based operating systems.<BR>
|
||||
Ports to other usable systems are appreciated. Reports are welcome.
|
||||
</P>
|
||||
|
||||
@ -76,111 +94,152 @@ Ports to other usable systems are appreciated. Reports are welcome.
|
||||
<P>
|
||||
<H2>Commands:</H2>
|
||||
<DL>
|
||||
<DT>The goal is to provide some of cdrecord's options in a compatible way.
|
||||
This has been achieved quite sufficiently for the needs of backup tool
|
||||
<A HREF="http://scdbackup.sourceforge.net/main_eng.html">scdbackup</A>
|
||||
and for data CD projects of <A HREF="http://www.k3b.org">K3b</A>
|
||||
(see <A HREF="#examples">examples</A>).
|
||||
Suitability for audio CD frontends has been improved much and is now being
|
||||
evaluated.<BR>
|
||||
Further enhancements depend on people who can describe and discuss their
|
||||
wishes as well as on the development of libburn.</DT>
|
||||
<DT>The most common options of cdrecord for data and audio on CD media
|
||||
are provided in a compatible way.<BR>
|
||||
On all DVD media, cdrskin is able to perform any recording job
|
||||
which is possible with cdrecord.
|
||||
Other than with cdrecord, option -multi is supported with many DVD types and
|
||||
BD-R. Write mode -tao works with anything but quickly blanked DVD-RW and
|
||||
DVD-R DL, which both support no -multi.
|
||||
</DT>
|
||||
<BR><BR>
|
||||
<DT>Get an overview of drives:</DT>
|
||||
<DD>$ cdrskin -scanbus</DD>
|
||||
<DD>$ cdrskin dev=ATA -scanbus</DD>
|
||||
<DD>$ cdrskin --devices</DD>
|
||||
<DT>Get an overview of drives and their addresses</DT>
|
||||
<DD>#<KBD> cdrskin -scanbus</KBD></DD>
|
||||
<DD>#<KBD> cdrskin dev=ATA -scanbus</KBD></DD>
|
||||
<DD>#<KBD> cdrskin --devices</KBD></DD>
|
||||
<DT>Being superuser avoids permission problems with /dev/srN resp. /dev/hdX .
|
||||
</DT>
|
||||
<DT>Ordinary users should then get granted access to the /dev files
|
||||
as listed by option --devices. Linux and FreeBSD demand rw-permission.
|
||||
On Solaris it is r-permission and privileges "basic,sys_devices".</DT>
|
||||
<DT> </DT>
|
||||
|
||||
<DT>Get info about a particular drive or loaded media:</DT>
|
||||
<DD>$ cdrskin dev=0,1,0 -checkdrive</DD>
|
||||
<DD>$ cdrskin dev=ATA:1,0,0 -atip</DD>
|
||||
<DD>$ cdrskin dev=/dev/hdc -toc</DD>
|
||||
<DT>Make used CD-RW writable again:</DT>
|
||||
<DD>$ cdrskin -v dev=/dev/sg1 blank=all -eject</DD>
|
||||
<DD>$ cdrskin -v dev=/dev/dvd blank=fast -eject</DD>
|
||||
<DT>Write ISO-9660 filesystem image:</DT>
|
||||
<DD>$ cdrskin -v dev=/dev/hdc speed=12 fs=8m driveropts=burnfree -sao -eject padsize=300k my_image.iso</DD>
|
||||
<DT>Write compressed afio archive on-the-fly:</DT>
|
||||
<DD>$ find . | afio -oZ - | cdrskin -v dev=0,1,0 fs=32m speed=8 driveropts=burnfree padsize=300k -sao tsize=650m -</DD>
|
||||
<DT>Write audio tracks:</DT>
|
||||
<DD>$ cdrskin -v dev=ATA:1,0,0 speed=48 driveropts=burnfree -sao track1.wav track2.au -audio -swab track3.raw
|
||||
<DD>
|
||||
<BR>
|
||||
<DT><A HREF="cdrskin_help">cdrskin -help</A></DT>
|
||||
<DD>reports the cdrecord compatible options</DD>
|
||||
<DT><A HREF="cdrskin__help">cdrskin --help</A></DT>
|
||||
<DD>reports the non-cdrecord options</DD>
|
||||
<DT><A HREF="http://cdrecord.berlios.de/old/private/man/cdrecord-2.0.html">man cdrecord</A></DT>
|
||||
<DD>documents the standard for which cdrskin is striving.
|
||||
<B>Do not bother Joerg Schilling with any cdrskin problems.</B>
|
||||
<DD>$<KBD> cdrskin dev=0,1,0 -checkdrive</KBD></DD>
|
||||
<DD>$<KBD> cdrskin dev=ATA:1,0,0 -v -atip</KBD></DD>
|
||||
<DD>$<KBD> cdrskin dev=/dev/hdc -minfo</KBD></DD>
|
||||
|
||||
<DT>Prepare CD-RW or DVD-RW for re-use, DVD-RAM or BD-RE for first use:</DT>
|
||||
<DD>$<KBD> cdrskin -v dev=/dev/sg1 blank=as_needed -eject</KBD></DD>
|
||||
|
||||
<DT>Format DVD-RW to avoid need for blanking before re-use:</DT>
|
||||
<DD>$<KBD> cdrskin -v dev=/dev/sr0 blank=format_overwrite</KBD></DD>
|
||||
|
||||
<DT>De-format DVD-RW to make it capable of multi-session again:</DT>
|
||||
<DD>$<KBD> cdrskin -v dev=/dev/sr0 blank=deformat_sequential</KBD></DD>
|
||||
|
||||
<DT>Write ISO-9660 filesystem image as only one to blank or formatted media:
|
||||
</DT>
|
||||
<DD>$<KBD> cdrskin -v dev=/dev/hdc speed=12 fs=8m \</KBD></DD>
|
||||
<DD><KBD> blank=as_needed -eject padsize=300k my_image.iso</KBD></DD>
|
||||
|
||||
<DT>Write compressed afio archive on-the-fly
|
||||
(not DVD-R DL or minimally blanked DVD-RW):</DT>
|
||||
<DD>$<KBD> find . | afio -oZ - | \</KBD></DD>
|
||||
<DD><KBD> cdrskin -v dev=0,1,0 fs=32m speed=8 \</KBD></DD>
|
||||
<DD><KBD> blank=as_needed padsize=300k -</KBD></DD>
|
||||
|
||||
<DT>Write several sessions to the same CD, DVD-R[W] or DVD+R[/DL]:</DT>
|
||||
<DD>$<KBD> cdrskin dev=/dev/hdc -v padsize=300k -multi 1.iso</KBD>
|
||||
</DD>
|
||||
<DD>$<KBD> cdrskin dev=/dev/hdc -v padsize=300k -multi 2.iso</KBD>
|
||||
</DD>
|
||||
<DD>$<KBD> cdrskin dev=/dev/hdc -v padsize=300k -multi 3.iso</KBD>
|
||||
</DD>
|
||||
<DD>$<KBD> cdrskin dev=/dev/hdc -v padsize=300k 4.iso</KBD></DD>
|
||||
|
||||
<DT>Get multi-session info for option -C of program mkisofs:</DT>
|
||||
<DD>$<KBD> c_values=$(cdrskin dev=/dev/sr0 -msinfo 2>/dev/null)</KBD></DD>
|
||||
<DD>$<KBD> mkisofs ... -C "$c_values" ...</KBD></DD>
|
||||
|
||||
<DT>Inquire free space on media for a -multi run:</DT>
|
||||
<DD>$<KBD> x=$(cdrskin dev=/dev/sr0 -multi \</KBD></DD>
|
||||
<DD><KBD> --tell_media_space 2>/dev/null)</KBD></DD>
|
||||
<DD>$<KBD> echo "Available: $x blocks of 2048 data bytes"</KBD></DD>
|
||||
|
||||
<DT>Accelerate BD-RE writing to full nominal speed after the first 250 MB</DT>
|
||||
<DD>$<KBD> cdrskin ... stream_recording=250m ...</KBD>
|
||||
|
||||
<DT>Write audio tracks to CD:</DT>
|
||||
<DD>$<KBD> cdrskin -v dev=ATA:1,0,0 speed=48 -sao \</KBD></DD>
|
||||
<DD><KBD> track1.wav track2.au -audio -swab track3.raw</KBD></DD>
|
||||
|
||||
<DT>Get overview of the cdrecord compatible options:</DT>
|
||||
<DD>$<KBD> <A HREF="cdrskin_help">cdrskin -help</A></KBD></DD>
|
||||
|
||||
<DT>Get overview of the non-cdrecord options:</DT>
|
||||
<DD>$<KBD> <A HREF="cdrskin__help">cdrskin --help</A></KBD></DD>
|
||||
|
||||
<DT>Read the detailed manual page:</DT>
|
||||
<DD>$<KBD> <A HREF="man_1_cdrskin.html">man cdrskin</A></KBD></DD>
|
||||
</DL>
|
||||
<DL>
|
||||
<DT>Read about the standard for which cdrskin is striving:</DT>
|
||||
<DD>$<KBD>
|
||||
<A HREF="http://cdrecord.berlios.de/old/private/man/cdrecord-2.0.html">
|
||||
man cdrecord</A></KBD></DD>
|
||||
<DD><B>Do not bother Joerg Schilling with any cdrskin problems.</B>
|
||||
(Be cursed if you install cdrskin as "cdrecord" without clearly forwarding
|
||||
this "don't bother Joerg" demand.)
|
||||
</DD>
|
||||
</DL>
|
||||
</P>
|
||||
<DL>
|
||||
<DT>Learn to know a more versatile way to burn ISO 9660 formatted data</DT>
|
||||
<DD>
|
||||
Standalone ISO 9660 multi-session CD/DVD/BD tool
|
||||
<A HREF="http://scdbackup.sourceforge.net/xorriso_eng.html">xorriso</A>.
|
||||
</DD>
|
||||
</DL>
|
||||
|
||||
<P>
|
||||
<H2>Known deficiencies:</H2>
|
||||
<UL>
|
||||
<DT></DT>
|
||||
<LI>
|
||||
Burns only a single closed session. No -multi option yet.
|
||||
</LI>
|
||||
<LI>
|
||||
No TAO mode and therefore no writing on-the-fly without a predefined
|
||||
source size.
|
||||
</LI>
|
||||
<LI>
|
||||
cdrskin -scanbus or --devices hangs for quite a while if there is
|
||||
a CD drive which does not work properly (e.g. because it has individual
|
||||
problems with DMA).
|
||||
So if the superuser gets no result with cdrskin --devices then one should
|
||||
disable DMA with the problematic CD drives
|
||||
(like: <KBD>hdparm -d0 /dev/hdd</KBD> )
|
||||
and try again.<BR>
|
||||
In severe cases it might be necessary to guess the device name /dev/sgN resp.
|
||||
/dev/hdX of the non-ill burner if it cannot be found otherwise among its
|
||||
ill peers. Alternatively one can guess the address of the ill device, remove
|
||||
rw-permissions and retry the bus scan as non-superuser.
|
||||
</UL>
|
||||
</P>
|
||||
|
||||
<HR>
|
||||
|
||||
<A NAME="download"></A>
|
||||
|
||||
<P>
|
||||
<DL>
|
||||
<DT>Download as source code (see README):</DT>
|
||||
<DD><A HREF="cdrskin-0.2.4.tar.gz">cdrskin-0.2.4.tar.gz</A>
|
||||
(510 KB).
|
||||
<DD><A HREF="cdrskin-1.1.0.tar.gz">cdrskin-1.1.0.tar.gz</A>
|
||||
(870 KB).
|
||||
</DD>
|
||||
<DD>
|
||||
The "stable" cdrskin tarballs are source code identical with "stable"
|
||||
libburn releases or with "stabilized" libburn SVN snapshots. They get
|
||||
produced via a different procedure, though.<BR>
|
||||
The cdrskin tarballs are source code identical with libburn releases
|
||||
of the same version number.
|
||||
They get produced via a different procedure, though.<BR>
|
||||
cdrskin is part of libburn - full libburn is provided with cdrskin releases.
|
||||
</DD>
|
||||
|
||||
<!-- This is not offered any more since spring 2008
|
||||
<DD> </DD>
|
||||
<DT>Download as single x86 binaries (untar and move to /usr/bin/cdrskin):</DT>
|
||||
<DD><A HREF="cdrskin_0.2.4-x86-suse9_0.tar.gz">
|
||||
cdrskin_0.2.4-x86-suse9_0.tar.gz</A>, (60 KB),
|
||||
<DD><A HREF="cdrskin_0.4.2.pl00-x86-suse9_0.tar.gz">
|
||||
cdrskin_0.4.2.pl00-x86-suse9_0.tar.gz</A>, (110 KB),
|
||||
<DL>
|
||||
<DD>runs on SuSE 9.0 (2.4.21) , RIP-14.4 (2.6.14) ,
|
||||
Gentoo (2.6.15 x86_64 Athlon).</DD>
|
||||
</DL>
|
||||
<DD><A HREF="cdrskin_0.2.4-x86-suse9_0-static.tar.gz">
|
||||
cdrskin_0.2.4-x86-suse9_0-static.tar.gz</A>, (260 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> a short introduction</DD>
|
||||
<DD><A HREF="README_cdrskin">README</A> an introduction</DD>
|
||||
<DD><A HREF="cdrskin__help">cdrskin --help</A> non-cdrecord options</DD>
|
||||
<DD><A HREF="cdrskin_help">cdrskin -help</A> cdrecord compatible options</DD>
|
||||
<DD><A HREF="man_1_cdrskin.html">man cdrskin</A> the manual page</DD>
|
||||
<DD> </DD>
|
||||
</DL>
|
||||
<DL><DT>Contact:</DT>
|
||||
<DD>Thomas Schmitt, <A HREF="mailto:scdbackup@gmx.net">scdbackup@gmx.net</A></DD>
|
||||
<DD>libburn development mailing list,
|
||||
<A HREF="mailto:libburn-hackers@pykix.org">libburn-hackers@pykix.org</A></DD>
|
||||
</DL>
|
||||
<DL><DT>License:</DT>
|
||||
<DD><A HREF="COPYING_cdrskin">GPL</A>, an <A HREF="http://www.opensource.org/">Open Source</A> approved license</DD>
|
||||
@ -191,46 +250,61 @@ cdrskin_0.2.4-x86-suse9_0-static.tar.gz</A>, (260 KB), -static compiled,
|
||||
<HR>
|
||||
|
||||
<P>
|
||||
Enhancements towards previous stable version cdrskin-0.2.2:
|
||||
Enhancements towards previous stable version cdrskin-1.0.6.pl00:
|
||||
<UL>
|
||||
<LI>cdrecord compatibility with drive addresses of form [ATA:]Bus,Target,Lun.
|
||||
<BR>(use option --old_pseudo_scsi_adr to get back the incompatible
|
||||
Bus,Traget,Lun addressing of version 0.2.2)
|
||||
<LI>none</LI>
|
||||
</LI>
|
||||
<LI>Drives adressable via links and device siblings (/dev/cdrom , /dev/scd0).
|
||||
</LI>
|
||||
<LI>Automatic -audio extraction with .wav files and .au files.
|
||||
</LI>
|
||||
<LI>Bug fix about failure to eject.</LI>
|
||||
<LI>Comments and empty lines allowed in startup files.</LI>
|
||||
<LI>Options -scanbus and --devices print SORRY messages about busy drives.
|
||||
</LI>
|
||||
<LI>Drive buffer fill indicator reports realistic percentage numbers.</LI>
|
||||
<LI>Option -toc is supported, drive firmware revision gets displayed.</LI>
|
||||
<!--
|
||||
<LI>none</LI>
|
||||
-->
|
||||
</UL>
|
||||
|
||||
Bug fixes towards cdrskin-1.0.6.pl00:
|
||||
<UL>
|
||||
<LI>
|
||||
Option -format as_needed issued a wrong block size.
|
||||
A Pioneer BDR-205 drive refused on that command.
|
||||
</LI>
|
||||
<!--
|
||||
<LI>none</LI>
|
||||
-->
|
||||
</UL>
|
||||
</P>
|
||||
|
||||
<HR>
|
||||
|
||||
<P>
|
||||
<DL>
|
||||
<DT>Development snapshot, version 0.2.5 :</DT>
|
||||
<DD> </DD>
|
||||
<DD>Enhancements towards stable version 0.2.4:
|
||||
<UL>
|
||||
<LI>-none for now-</LI>
|
||||
</UL>
|
||||
<DT><H3>Development snapshot, version 1.1.1 :</H3></DT>
|
||||
<DD>Enhancements towards current stable version 1.0.0:
|
||||
<UL>
|
||||
<LI>none yet</LI>
|
||||
<!--
|
||||
<LI>none yet</LI>
|
||||
-->
|
||||
|
||||
</UL>
|
||||
</DD>
|
||||
|
||||
<DD>Bug fixes towards cdrskin-1.1.0:
|
||||
<UL>
|
||||
<LI>none yet</LI>
|
||||
<!--
|
||||
<LI>none yet</LI>
|
||||
-->
|
||||
</UL>
|
||||
</DD>
|
||||
|
||||
<DD> </DD>
|
||||
<DD><A HREF="README_cdrskin_devel">README 0.2.5</A>
|
||||
<DD><A HREF="cdrskin__help_devel">cdrskin_0.2.5 --help</A></DD>
|
||||
<DD><A HREF="cdrskin_help_devel">cdrskin_0.2.5 -help</A></DD>
|
||||
<DD><A HREF="README_cdrskin_devel">README 1.1.1</A>
|
||||
<DD><A HREF="cdrskin__help_devel">cdrskin-1.1.1 --help</A></DD>
|
||||
<DD><A HREF="cdrskin_help_devel">cdrskin-1.1.1 -help</A></DD>
|
||||
<DD><A HREF="man_1_cdrskin_devel.html">man cdrskin (as of 1.1.1)</A></DD>
|
||||
<DD> </DD>
|
||||
<DT>Maintainers of cdrskin unstable packages please use SVN of
|
||||
<A HREF="http://libburn.pykix.org"> libburn.pykix.org</A></DT>
|
||||
<DD>Download: <KBD><B>svn co http://libburn-svn.pykix.org/trunk libburn_pykix</B>
|
||||
<A HREF="http://libburnia-project.org"> libburnia-project.org</A></DT>
|
||||
<DD>Download: <KBD><B>svn co http://svn.libburnia-project.org/libburn/trunk libburn</B>
|
||||
</KBD></DD>
|
||||
<DD>Build: <KBD><B>cd libburn_pykix ; ./bootstrap ; ./configure ; make</B>
|
||||
<DD>Build: <KBD><B>cd libburn ; ./bootstrap ; ./configure --prefix /usr ; make ; cdrskin/compile_cdrskin.sh</B>
|
||||
</KBD></DD>
|
||||
<DD>Build of SVN versions needs <A HREF="http://sources.redhat.com/autobook/">
|
||||
autotools</A> of at least version 1.7 installed.
|
||||
@ -238,22 +312,29 @@ But after the run of <KBD>./bootstrap</KBD>, only
|
||||
vanilla tools like make and gcc are needed.</DD>
|
||||
</DD>
|
||||
<DD> </DD>
|
||||
<DT>The following downloads are intended for adventurous end users or
|
||||
<DT>The following download is intended for adventurous end users or
|
||||
admins with full system souvereignty.</DT>
|
||||
<DD>Source (./bootstrap is already applied, build tested, for more see above
|
||||
<DD>Source (./bootstrap is already applied, build tested, for more see
|
||||
<A HREF="README_cdrskin_devel">upcoming README</A> ):
|
||||
</DD>
|
||||
<DD>
|
||||
<A HREF="cdrskin-0.2.5.tar.gz">cdrskin-0.2.5.tar.gz</A>
|
||||
(500 KB).
|
||||
<A HREF="cdrskin-1.1.1.tar.gz">cdrskin-1.1.1.tar.gz</A>
|
||||
(870 KB).
|
||||
</DD>
|
||||
|
||||
<!-- This is not offered any more since spring 2008
|
||||
|
||||
<DT>The following downloads are intended for adventurous end users or
|
||||
admins with full system souvereignty.</DT>
|
||||
<DD>Binary (untar and move to /usr/bin/cdrskin):</DD>
|
||||
<DD><A HREF="cdrskin_0.2.5-x86-suse9_0.tar.gz">
|
||||
cdrskin_0.2.5-x86-suse9_0.tar.gz</A>, (60 KB).
|
||||
<DD><A HREF="cdrskin_0.4.3-x86-suse9_0.tar.gz">
|
||||
cdrskin_0.4.3-x86-suse9_0.tar.gz</A>, (110 KB).
|
||||
</DD>
|
||||
<DD><A HREF="cdrskin_0.2.5-x86-suse9_0-static.tar.gz">
|
||||
cdrskin_0.2.5-x86-suse9_0-static.tar.gz</A>, (260 KB)
|
||||
<DD><A HREF="cdrskin_0.4.3-x86-suse9_0-static.tar.gz">
|
||||
cdrskin_0.4.3-x86-suse9_0-static.tar.gz</A>, (310 KB)
|
||||
</DD>
|
||||
-->
|
||||
|
||||
</DL>
|
||||
</P>
|
||||
|
||||
@ -268,6 +349,10 @@ Historic versions based on Derek's and Ben's
|
||||
<A HREF="http://icculus.org/burn">icculus.org/burn</A> :<BR>
|
||||
<A HREF="cdrskin-0.1.2.0.2.ts.tar.gz">cdrskin-0.1.2.0.2.ts.tar.gz</A><BR>
|
||||
<A HREF="cdrskin-0.1.3.0.2.ts.tar.gz">cdrskin-0.1.3.0.2.ts.tar.gz</A>
|
||||
<BR>
|
||||
Very special thanks to Andy Polyakov whose
|
||||
<A HREF="http://fy.chalmers.se/~appro/linux/DVD+RW/tools">dvd+rw-tools</A>
|
||||
provide libburn with invaluable examples on how to deal with DVD and BD media.
|
||||
</P>
|
||||
|
||||
<HR>
|
||||
@ -275,14 +360,33 @@ Historic versions based on Derek's and Ben's
|
||||
<A NAME="examples">
|
||||
<P>
|
||||
<DL>
|
||||
<DT>Example for a setup of device permissions. To be done by the superuser:</DT>
|
||||
<DT>(CD devices which offer no r-permission are invisible to normal users.)</DT>
|
||||
<DT>(CD devices which offer no w-permission are not useable.)</DT>
|
||||
<DT>Example for a setup of device permissions.</DT>
|
||||
<DT>
|
||||
Newer Linux distros enable rw-access for the desktop user automatically.
|
||||
So try as normal user whether all your drives are found.
|
||||
CD devices which offer no rw-permission will stay invisible.
|
||||
</DT>
|
||||
<DD>$ <KBD><B>cdrskin --devices</B></KBD></DD>
|
||||
<DT>If not all desired drives show up, become superuser and do again:</DT>
|
||||
</DT>
|
||||
<DD># <KBD><B>cdrskin --devices</B></KBD></DD>
|
||||
<DD><KBD>...</KBD></DD>
|
||||
<DD><KBD>0 dev='/dev/sg0' rwrwr- : 'TEAC' 'CD-ROM CD-532S'</KBD></DD>
|
||||
<DD><KBD>0 dev='/dev/sr0' rwr-r- : 'TEAC' 'CD-ROM CD-532S'</KBD></DD>
|
||||
<DD><KBD>1 dev='/dev/hdc' rwrw-- : 'LITE-ON' 'LTR-48125S'</KBD></DD>
|
||||
<DD># <KBD><B>chmod a+rw /dev/sg0 /dev/hdc</B></KBD></DD>
|
||||
<DT>Most simple and most insecure is this equivalent
|
||||
of the usual cdrecord permissions u+s,a+x:</DT>
|
||||
<DD># <KBD><B>chmod a+rw /dev/sr0 /dev/hdc</B></KBD></DD>
|
||||
<DT>
|
||||
More secure is to put the permitted users into a group like
|
||||
"floppy", to assign /dev/sr0 /dev/hdc to this group,
|
||||
and to allow rw-access only to group members.
|
||||
</DT>
|
||||
<DD># <KBD><B>vi /etc/group</B></KBD></DD>
|
||||
<DD><KBD>...</KBD></DD>
|
||||
<DD><KBD>floppy:x:19:thomas,scdbackup</KBD></DD>
|
||||
<DD><KBD>...</KBD></DD>
|
||||
<DD># <KBD><B>chgrp floppy /dev/sr0 /dev/hdc</B></KBD></DD>
|
||||
<DD># <KBD><B>chmod g+rw /dev/sr0 /dev/hdc</B></KBD></DD>
|
||||
</DL>
|
||||
</P>
|
||||
|
||||
@ -297,6 +401,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">
|
||||
@ -305,20 +411,12 @@ is a GUI frontend which uses cdrecord for CD burning.)
|
||||
<DT>Example for a test session with a cdrecord based scdbackup installation:</DT>
|
||||
<DD>$ <KBD><B>cdrskin -scanbus</B></KBD></DD>
|
||||
<DD><KBD>...</KBD></DD>
|
||||
</DL>
|
||||
If your system is stricken with some ill CD device then this can stall
|
||||
and you will have to press <KBD>Ctrl+C</KBD> to abort.
|
||||
In this case, you may execute
|
||||
<KBD>export SCDBACKUP_NO_SCANBUS=1</KBD>
|
||||
and try again.
|
||||
<DL>
|
||||
<DT></DT>
|
||||
<DD><KBD> 2,0,0 0) 'TEAC' 'CD-ROM CD-532S' '?' Removable CD-ROM</KBD></DD>
|
||||
<DD>$ <KBD><B>cdrskin -scanbus dev=ATA</B></KBD></DD>
|
||||
<DD><KBD>...</KBD></DD>
|
||||
<DD><KBD> 1,0,0 1) 'LITE-ON' 'LTR-48125S' '?' Removable CD-ROM</KBD></DD>
|
||||
<DD>$ <KBD><B>export SCDBACKUP_SCSI_ADR="ATA:1,0,0"</B></KBD></DD>
|
||||
<DD>$ <KBD><B>export SCDBACKUP_CDRECORD="cdrskin -v -v tao_to_sao_tsize=650m"</B></KBD></DD>
|
||||
<DD>$ <KBD><B>export SCDBACKUP_CDRECORD="cdrskin -v -v"</B></KBD></DD>
|
||||
<DD>$ <KBD><B>scdbackup_home</B></KBD></DD>
|
||||
</DL>
|
||||
<DL>
|
||||
@ -327,8 +425,15 @@ and try again.
|
||||
<DD>$ <KBD><B>export SCDBACKUP_USE_CDRSKIN=1</B></KBD></DD>
|
||||
<DD>$ <KBD><B>./CONFIGURE_CD</B></KBD></DD>
|
||||
<DD><KBD>...</KBD></DD>
|
||||
<DD><KBD>cdrskin 0.2.4 : limited cdrecord compatibility wrapper for libburn</KBD></DD>
|
||||
<DD><KBD>...</KBD></DD>
|
||||
<DD><KBD>cdrskin 0.3.8 : limited cdrecord compatibility wrapper for libburn</KBD></DD>
|
||||
</DL>
|
||||
If your system is stricken with some ill CD device then this can stall
|
||||
and you will have to press <KBD>Ctrl+C</KBD> to abort.
|
||||
In this case, you may execute
|
||||
<KBD>export SCDBACKUP_NO_SCANBUS=1</KBD>
|
||||
and try again.
|
||||
<DL>
|
||||
<DT></DT>
|
||||
<DD><KBD> ------------------- SCSI devices. To be used like 0,0,0</KBD></DD>
|
||||
<DD><KBD> 2,0,0 0) 'TEAC' 'CD-ROM CD-532S' '?' Removable CD-ROM</KBD></DD>
|
||||
<DD><KBD> ------------------- end of SCSI device list</KBD></DD>
|
||||
@ -352,6 +457,8 @@ and try again.
|
||||
</DL>
|
||||
</P>
|
||||
|
||||
-->
|
||||
|
||||
<HR>
|
||||
|
||||
<A NAME="cdrecord">
|
||||
@ -364,7 +471,7 @@ cdrecord but not vice versa.
|
||||
I am a long time user of cdrecord and it works fine for me.
|
||||
Especially i do appreciate its write mode -tao which allows to pipe arbitrary
|
||||
data on CD and CD-RW via stdin. cdrecord is reliable, versatile and well
|
||||
maintained. So for me - there would be not problem with it.
|
||||
maintained. So for me - there would be no problem with it.
|
||||
<BR>
|
||||
But the author of cdrecord and the Linux kernel people foster a very hostile
|
||||
relationship. Ok, that's their business, not mine (or ours if you are with me).
|
||||
@ -378,10 +485,11 @@ the gestures necessary for their cdrecord applications.
|
||||
Contact me. Let's see what we can achieve.
|
||||
<BR>
|
||||
<BR>
|
||||
I am aware that libburn and cdrskin still have way to go until you can simply
|
||||
install cdrskin as cdrecord and may expect any application to run with it.
|
||||
Currently i do not encourage this approach, but of course such a replacement
|
||||
opportunity is the long term goal of a cdrecord compatibility wrapper.
|
||||
libburn and cdrskin are now mature enough to substitute cdrecord in its
|
||||
major use cases of CD and DVD burning. It is possible to foist cdrskin on
|
||||
various software packages if it gets falsely named "cdrecord".
|
||||
I do not encourage this approach, but of course such a replacement
|
||||
opportunity is the goal of a cdrecord compatibility wrapper.
|
||||
<BR>
|
||||
<BR>
|
||||
It is very important to me that this project is not perceived as hostile
|
||||
@ -395,6 +503,10 @@ I owe him much. For cdrecord, for mkisofs, for star. Chapeau.
|
||||
<!-- <A NAME="bottom" HREF="main_ger.html#bottom">deutsch (german)</A>
|
||||
<BR><BR>
|
||||
-->
|
||||
<A HREF="http://en.wikipedia.org/wiki/D%C3%B6ner_kebab">
|
||||
<IMG SRC="doener_150x200_tr.png" BORDER=0
|
||||
ALT="cdrskin logo: Doener mit Scharf"></A>
|
||||
<BR><BR>
|
||||
<FONT SIZE=+0>Enjoying free Open Source hosting by <A HREF="http://www.webframe.org">www.webframe.org</A><BR>
|
||||
<A HREF="http://www.webframe.org">
|
||||
<IMG SRC="msfree.gif" ALT="100 % Microsoft free" BORDER=0></A><BR>
|
||||
@ -402,18 +514,34 @@ and by <A HREF="http://sourceforge.net">sourceforge.net</A><BR>
|
||||
<A href="http://sourceforge.net">
|
||||
<IMG src="sflogo-88-1.png" BORDER="0" ALT="SourceForge Logo"></A>
|
||||
<!-- on sourceforge use : <IMG src="http://sourceforge.net/sflogo.php?group_id=16010" width="88" height="31" border="0" alt="SourceForge Logo"></A> -->
|
||||
<P>
|
||||
Enjoying a FreeBSD shell account with the opportunity to
|
||||
build and install cdrskin at<BR>
|
||||
<A HREF="http://www.en.free-shells.com.ar">free-shells.com.ar</A>
|
||||
</P>
|
||||
</FONT></CENTER>
|
||||
<HR>
|
||||
<DL>
|
||||
<DT>Links to my other published software projects :
|
||||
<DD><A HREF="http://scdbackup.webframe.org/xorriso_eng.html">
|
||||
xorriso, a standalone ISO 9660 multi-session CD/DVD/BD 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>
|
||||
|
@ -1 +1 @@
|
||||
#define Cdrskin_timestamP "2006.11.02.140329 (pl01)"
|
||||
#define Cdrskin_timestamP "2011.06.20.110001"
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -23,31 +23,27 @@ typedef void (*sighandler_t)(int);
|
||||
|
||||
#include "cleanup.h"
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#ifndef Cleanup_has_no_libburn_os_H
|
||||
|
||||
|
||||
#include "../libburn/os.h"
|
||||
|
||||
/* see os.h for name of particular os-*.h where this is defined */
|
||||
static int signal_list[]= { BURN_OS_SIGNAL_MACRO_LIST , -1};
|
||||
static char *signal_name_list[]= { BURN_OS_SIGNAL_NAME_LIST , "@"};
|
||||
static int signal_list_count= BURN_OS_SIGNAL_COUNT;
|
||||
static int non_signal_list[]= { BURN_OS_NON_SIGNAL_MACRO_LIST, -1};
|
||||
static int non_signal_list_count= BURN_OS_NON_SIGNAL_COUNT;
|
||||
|
||||
|
||||
#else /* ! Cleanup_has_no_libburn_os_H */
|
||||
|
||||
|
||||
/* Outdated. Linux only. For backward compatibility with pre-libburn-0.2.3 */
|
||||
|
||||
/* Signals to be caught */
|
||||
static int signal_list[]= {
|
||||
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT,
|
||||
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM,
|
||||
SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN,
|
||||
SIGTTOU,
|
||||
SIGBUS, SIGPROF, SIGSYS, SIGTRAP,
|
||||
SIGVTALRM, SIGXCPU, SIGXFSZ, -1
|
||||
};
|
||||
static char *signal_name_list[]= {
|
||||
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT",
|
||||
"SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM",
|
||||
"SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN",
|
||||
"SIGTTOU",
|
||||
"SIGBUS", "SIGPROF", "SIGSYS", "SIGTRAP",
|
||||
"SIGVTALRM", "SIGXCPU", "SIGXFSZ", "@"
|
||||
};
|
||||
static int signal_list_count= 23;
|
||||
|
||||
#else /* __FreeBSD__ */
|
||||
|
||||
/* Signals to be caught */
|
||||
static int signal_list[]= {
|
||||
static int signal_list[]= {
|
||||
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT,
|
||||
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM,
|
||||
SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN,
|
||||
@ -55,7 +51,7 @@ static int signal_list[]= {
|
||||
SIGBUS, SIGPOLL, SIGPROF, SIGSYS, SIGTRAP,
|
||||
SIGVTALRM, SIGXCPU, SIGXFSZ, -1
|
||||
};
|
||||
static char *signal_name_list[]= {
|
||||
static char *signal_name_list[]= {
|
||||
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT",
|
||||
"SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM",
|
||||
"SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN",
|
||||
@ -65,18 +61,21 @@ static char *signal_name_list[]= {
|
||||
};
|
||||
static int signal_list_count= 24;
|
||||
|
||||
#endif /* ! __FreeBSD__ */
|
||||
|
||||
/* Signals not to be caught */
|
||||
static int non_signal_list[]= {
|
||||
SIGKILL, SIGCHLD, SIGSTOP, SIGURG, -1
|
||||
};
|
||||
static int non_signal_list_count= 4;
|
||||
SIGKILL, SIGCHLD, SIGSTOP, SIGURG, SIGWINCH, -1
|
||||
};
|
||||
static int non_signal_list_count= 5;
|
||||
|
||||
|
||||
#endif /* Cleanup_has_no_libburn_os_H */
|
||||
|
||||
|
||||
|
||||
/* run time dynamic part */
|
||||
static char cleanup_msg[4096]= {""};
|
||||
static int cleanup_exiting= 0;
|
||||
static int cleanup_has_reported= -1234567890;
|
||||
|
||||
static void *cleanup_app_handle= NULL;
|
||||
static Cleanup_app_handler_T cleanup_app_handler= NULL;
|
||||
@ -87,8 +86,10 @@ static int Cleanup_handler_exit(int exit_value, int signum, int flag)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if(cleanup_msg[0]!=0)
|
||||
if(cleanup_msg[0]!=0 && cleanup_has_reported!=signum) {
|
||||
fprintf(stderr,"\n%s\n",cleanup_msg);
|
||||
cleanup_has_reported= signum;
|
||||
}
|
||||
if(cleanup_perform_app_handler_first)
|
||||
if(cleanup_app_handler!=NULL) {
|
||||
ret= (*cleanup_app_handler)(cleanup_app_handle,signum,0);
|
||||
|
@ -1,23 +1,38 @@
|
||||
#!/bin/sh
|
||||
|
||||
# compile_cdrskin.sh
|
||||
# Copyright 2005 - 2006 Thomas Schmitt, scdbackup@gmx.net, GPL
|
||||
# Copyright 2005 - 2011 Thomas Schmitt, scdbackup@gmx.net, GPL
|
||||
# to be executed within ./libburn-* resp ./cdrskin-*
|
||||
|
||||
debug_opts=
|
||||
debug_opts="-O2"
|
||||
def_opts=
|
||||
libvers="-DCdrskin_libburn_0_2_3"
|
||||
cleanup_src_or_obj="libburn/cleanup.o"
|
||||
libdax_msgs_o="libburn/libdax_msgs.o"
|
||||
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
|
||||
largefile_opts="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1"
|
||||
fifo_opts=""
|
||||
libvers="-DCdrskin_libburn_1_1_0"
|
||||
|
||||
# To be used if Makefile.am uses libburn_libburn_la_CFLAGS
|
||||
# burn="libburn/libburn_libburn_la-"
|
||||
burn="libburn/"
|
||||
|
||||
cleanup_src_or_obj="$burn"cleanup.o
|
||||
libdax_msgs_o="$burn"libdax_msgs.o
|
||||
libdax_audioxtr_o="$burn"libdax_audioxtr.o
|
||||
do_strip=0
|
||||
static_opts=
|
||||
warn_opts="-Wall"
|
||||
libcdio=
|
||||
fifo_source="cdrskin/cdrfifo.c"
|
||||
compile_cdrskin=1
|
||||
compile_cdrfifo=0
|
||||
compile_dewav=0
|
||||
|
||||
libcam=
|
||||
os=$(uname -s)
|
||||
case $os in
|
||||
*FreeBSD)
|
||||
libcam="-lcam"
|
||||
esac
|
||||
|
||||
for i in "$@"
|
||||
do
|
||||
if test "$i" = "-compile_cdrfifo"
|
||||
@ -30,26 +45,33 @@ do
|
||||
then
|
||||
libvers="-DCdrskin_libburn_cvs_A60220_tS"
|
||||
libdax_audioxtr_o=
|
||||
libdax_msgs_o="libburn/message.o"
|
||||
cleanup_src_or_obj="cdrskin/cleanup.c"
|
||||
elif test "$i" = "-libburn_0_2_2"
|
||||
libdax_msgs_o="$burn"message.o
|
||||
cleanup_src_or_obj="-DCleanup_has_no_libburn_os_H cdrskin/cleanup.c"
|
||||
elif test "$i" = "-libburn_1_1_0"
|
||||
then
|
||||
libvers="-DCdrskin_libburn_0_2_2"
|
||||
libdax_audioxtr_o=
|
||||
libdax_msgs_o="libburn/message.o"
|
||||
cleanup_src_or_obj="cdrskin/cleanup.c"
|
||||
elif test "$i" = "-libburn_0_2_3"
|
||||
libvers="-DCdrskin_libburn_1_1_0"
|
||||
libdax_audioxtr_o="$burn"libdax_audioxtr.o
|
||||
libdax_msgs_o="$burn"libdax_msgs.o
|
||||
cleanup_src_or_obj="$burn"cleanup.o
|
||||
elif test "$i" = "-libburn_svn"
|
||||
then
|
||||
libvers="-DCdrskin_libburn_0_2_3"
|
||||
libdax_audioxtr_o="libburn/libdax_audioxtr.o"
|
||||
libdax_msgs_o="libburn/libdax_msgs.o"
|
||||
cleanup_src_or_obj="libburn/cleanup.o"
|
||||
libvers="-DCdrskin_libburn_1_1_1"
|
||||
libdax_audioxtr_o="$burn"libdax_audioxtr.o
|
||||
libdax_msgs_o="$burn"libdax_msgs.o
|
||||
cleanup_src_or_obj="$burn"cleanup.o
|
||||
elif test "$i" = "-newapi" -o "$i" = "-experimental"
|
||||
then
|
||||
def_opts="$def_opts -DCdrskin_new_api_tesT"
|
||||
elif test "$i" = "-oldfashioned"
|
||||
then
|
||||
def_opts="$def_opts -DCdrskin_oldfashioned_api_usE"
|
||||
cleanup_src_or_obj="-DCleanup_has_no_libburn_os_H cdrskin/cleanup.c"
|
||||
elif test "$i" = "-no_largefile"
|
||||
then
|
||||
largefile_opts=
|
||||
elif test "$i" = "-dvd_obs_64k"
|
||||
then
|
||||
def_opts="$def_opts -DCdrskin_dvd_obs_default_64K"
|
||||
elif test "$i" = "-do_not_compile_cdrskin"
|
||||
then
|
||||
compile_cdrskin=0
|
||||
@ -61,28 +83,44 @@ do
|
||||
elif test "$i" = "-do_strip"
|
||||
then
|
||||
do_strip=1
|
||||
elif test "$i" = "-use_libburn_fifo"
|
||||
then
|
||||
fifo_opts="-DCdrskin_use_libburn_fifO"
|
||||
elif test "$i" = "-use_no_libburn_fifo"
|
||||
then
|
||||
fifo_opts=""
|
||||
elif test "$i" = "-use_no_cdrfifo"
|
||||
then
|
||||
fifo_source=
|
||||
fifo_opts="-DCdrskin_use_libburn_fifO -DCdrskin_no_cdrfifO"
|
||||
elif test "$i" = "-use_libburn_cleanup"
|
||||
then
|
||||
fifo_source=
|
||||
fifo_opts="-DCdrskin_use_libburn_cleanuP -DCdrskin_use_libburn_fifO -DCdrskin_no_cdrfifO"
|
||||
elif test "$i" = "-use_libcdio"
|
||||
then
|
||||
libcdio="-lcdio"
|
||||
elif test "$i" = "-g"
|
||||
then
|
||||
debug_opts="$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"
|
||||
echo "Options:"
|
||||
echo " -compile_cdrfifo compile program cdrskin/cdrfifo."
|
||||
echo " -compile_dewav compile program test/dewav without libburn."
|
||||
echo " -cvs_A60220 set macro to match libburn-CVS of 20 Feb 2006."
|
||||
echo " -libburn_0_2_2 set macro to match libburn-0.2.2."
|
||||
echo " -libburn_0_2_3 set macro to match current libburn-SVN."
|
||||
echo " -libburn_1_1_0 set macro to match libburn-1.1.0"
|
||||
echo " -libburn_svn set macro to match current libburn-SVN."
|
||||
echo " -dvd_obs_64k 64 KB default size for DVD/BD writing."
|
||||
echo " -use_libcdio link with -lcdio because libburn uses it."
|
||||
echo " -do_not_compile_cdrskin omit compilation of cdrskin/cdrskin."
|
||||
echo " -use_no_libburn_fifo use cdrfifo even for single track non-CD"
|
||||
echo " -use_no_cdrfifo always use fifo of libburn and never cdrfifo"
|
||||
echo " -experimental use newly introduced libburn features."
|
||||
echo " -oldfashioned use pre-0.2.2 libburn features only."
|
||||
echo " -do_diet produce capability reduced lean version."
|
||||
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"
|
||||
@ -98,8 +136,16 @@ echo "Build timestamp : $timestamp"
|
||||
|
||||
if test "$compile_cdrskin"
|
||||
then
|
||||
echo "compiling program cdrskin/cdrskin.c $static_opts $debug_opts $libvers $def_opts $cleanup_src_or_obj"
|
||||
cc $warn_opts -I. $static_opts $debug_opts $libvers $def_opts \
|
||||
echo "compiling program cdrskin/cdrskin.c $fifo_source $static_opts $debug_opts $libvers $fifo_opts $def_opts $cleanup_src_or_obj $libcdio $libcam"
|
||||
cc -I. \
|
||||
$warn_opts \
|
||||
$static_opts \
|
||||
$debug_opts \
|
||||
$libvers \
|
||||
$largefile_opts \
|
||||
$fifo_opts \
|
||||
$def_opts \
|
||||
\
|
||||
-DCdrskin_build_timestamP='"'"$timestamp"'"' \
|
||||
\
|
||||
-o cdrskin/cdrskin \
|
||||
@ -109,31 +155,34 @@ then
|
||||
\
|
||||
$cleanup_src_or_obj \
|
||||
\
|
||||
libburn/async.o \
|
||||
libburn/debug.o \
|
||||
libburn/drive.o \
|
||||
libburn/file.o \
|
||||
libburn/init.o \
|
||||
libburn/options.o \
|
||||
libburn/source.o \
|
||||
libburn/structure.o \
|
||||
"$burn"async.o \
|
||||
"$burn"debug.o \
|
||||
"$burn"drive.o \
|
||||
"$burn"file.o \
|
||||
"$burn"init.o \
|
||||
"$burn"options.o \
|
||||
"$burn"source.o \
|
||||
"$burn"structure.o \
|
||||
\
|
||||
libburn/sg.o \
|
||||
libburn/write.o \
|
||||
"$burn"sg.o \
|
||||
"$burn"write.o \
|
||||
"$burn"read.o \
|
||||
$libdax_audioxtr_o \
|
||||
$libdax_msgs_o \
|
||||
\
|
||||
libburn/mmc.o \
|
||||
libburn/sbc.o \
|
||||
libburn/spc.o \
|
||||
libburn/util.o \
|
||||
"$burn"mmc.o \
|
||||
"$burn"sbc.o \
|
||||
"$burn"spc.o \
|
||||
"$burn"util.o \
|
||||
\
|
||||
libburn/sector.o \
|
||||
libburn/toc.o \
|
||||
"$burn"sector.o \
|
||||
"$burn"toc.o \
|
||||
\
|
||||
libburn/crc.o \
|
||||
libburn/lec.o \
|
||||
"$burn"crc.o \
|
||||
"$burn"ecma130ab.o \
|
||||
\
|
||||
$libcdio \
|
||||
$libcam \
|
||||
-lpthread
|
||||
|
||||
ret=$?
|
||||
@ -175,8 +224,8 @@ then
|
||||
-DDewav_without_libburN \
|
||||
-o test/dewav \
|
||||
test/dewav.c \
|
||||
libburn/libdax_audioxtr.o \
|
||||
libburn/libdax_msgs.o \
|
||||
"$burn"libdax_audioxtr.o \
|
||||
"$burn"libdax_msgs.o \
|
||||
\
|
||||
-lpthread
|
||||
|
||||
|
78
cdrskin/convert_man_to_html.sh
Executable file
78
cdrskin/convert_man_to_html.sh
Executable file
@ -0,0 +1,78 @@
|
||||
#!/bin/sh
|
||||
|
||||
#
|
||||
# convert_man_to_html.sh - ts A61214
|
||||
#
|
||||
# Generates a HTML version of man page cdrskin.1
|
||||
#
|
||||
# To be executed within the libburn toplevel directory (like ./libburn-0.2.7)
|
||||
#
|
||||
|
||||
# set -x
|
||||
|
||||
man_dir=$(pwd)"/cdrskin"
|
||||
export MANPATH="$man_dir"
|
||||
manpage="cdrskin"
|
||||
raw_html=$(pwd)/"cdrskin/raw_man_1_cdrskin.html"
|
||||
htmlpage=$(pwd)/"cdrskin/man_1_cdrskin.html"
|
||||
|
||||
if test -r "$man_dir"/"$manpage".1
|
||||
then
|
||||
dummy=dummy
|
||||
else
|
||||
echo "Cannot find readable man page source $1" >&2
|
||||
exit 1
|
||||
fi
|
||||
|
||||
if test -e "$man_dir"/man1
|
||||
then
|
||||
dummy=dummy
|
||||
else
|
||||
ln -s . "$man_dir"/man1
|
||||
fi
|
||||
|
||||
if test "$1" = "-work_as_filter"
|
||||
then
|
||||
|
||||
# set -x
|
||||
|
||||
sed \
|
||||
-e 's/<meta name="generator" content="groff -Thtml, see www.gnu.org">/<meta name="generator" content="groff -Thtml, via man -H, via cdrskin\/convert_man_to_html.sh">/' \
|
||||
-e 's/<meta name="Content-Style" content="text\/css">/<meta name="Content-Style" content="text\/css"><META NAME="description" CONTENT="man page of cdrskin"><META NAME="keywords" CONTENT="man cdrskin, manual, cdrskin, CD, CD-RW, CD-R, burning, cdrecord, compatible"><META NAME="robots" CONTENT="follow">/' \
|
||||
-e 's/<title>CDRSKIN<\/title>/<title>man 1 cdrskin<\/title>/' \
|
||||
-e 's/<h1 align=center>CDRSKIN<\/h1>/<h1 align=center>man 1 cdrskin<\/h1>/' \
|
||||
-e 's/<body>/<body BGCOLOR="#F5DEB3" TEXT=#000000 LINK=#0000A0 VLINK=#800000>/' \
|
||||
-e 's/<b>Overview of features:<\/b>/\ <BR><b>Overview of features:<\/b>/' \
|
||||
-e 's/<b>General information paragraphs:<\/b>/\ <BR><b>General information paragraphs:<\/b>/' \
|
||||
-e 's/<b>Track recording model:<\/b>/\ <BR><b>Track recording model:<\/b>/' \
|
||||
-e 's/^In general there are two types of tracks: data and audio./\ <BR>In general there are two types of tracks: data and audio./' \
|
||||
-e 's/^While audio tracks just contain a given/\ <BR>While audio tracks just contain a given/' \
|
||||
-e 's/<b>Write mode selection:<\/b>/\ <BR><b>Write mode selection:<\/b>/' \
|
||||
-e 's/<b>Recordable CD Media:<\/b>/\ <BR><b>Recordable CD Media:<\/b>/' \
|
||||
-e 's/<b>Overwriteable DVD Media:<\/b>/\ <BR><b>Overwriteable DVD Media:<\/b>/' \
|
||||
-e 's/<b>Sequentially Recordable DVD Media:<\/b>/\ <BR><b>Sequentially Recordable DVD Media:<\/b>/' \
|
||||
-e 's/^The write modes for DVD+R/\ <BR>The write modes for DVD+R/' \
|
||||
-e 's/<b>Drive preparation and addressing:<\/b>/\ <BR><b>Drive preparation and addressing:<\/b>/' \
|
||||
-e 's/^If you only got one CD capable drive/\ <BR>If you only got one CD capable drive/' \
|
||||
-e 's/<b>Emulated drives:<\/b>/\ <BR><b>Emulated drives:<\/b>/' \
|
||||
-e 's/^Alphabetical list of options/\ <BR>Alphabetical list of options/' \
|
||||
-e 's/<\/body>/<BR><HR><FONT SIZE=-1><CENTER>(HTML generated from '"$manpage"'.1 on '"$(date)"' by '$(basename "$0")' )<\/CENTER><\/FONT><\/body>/' \
|
||||
-e 's/See section FILES/See section <A HREF="#FILES">FILES<\/A>/' \
|
||||
-e 's/See section EXAMPLES/See section <A HREF="#EXAMPLES">EXAMPLES<\/A>/' \
|
||||
<"$2" >"$htmlpage"
|
||||
|
||||
set +x
|
||||
|
||||
chmod u+rw,go+r,go-w "$htmlpage"
|
||||
echo "Emerged file:"
|
||||
ls -lL "$htmlpage"
|
||||
|
||||
else
|
||||
|
||||
export BROWSER='cp "%s" '"$raw_html"
|
||||
man -H "$manpage"
|
||||
"$0" -work_as_filter "$raw_html"
|
||||
rm "$raw_html"
|
||||
rm "$man_dir"/man1
|
||||
|
||||
fi
|
BIN
cdrskin/doener_150x200_tr.png
Normal file
BIN
cdrskin/doener_150x200_tr.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 10 KiB |
BIN
cdrskin/doener_150x200_tr_octx.png
Normal file
BIN
cdrskin/doener_150x200_tr_octx.png
Normal file
Binary file not shown.
After Width: | Height: | Size: 9.2 KiB |
@ -1,54 +1,62 @@
|
||||
--------------------------------------------------------------------------
|
||||
cdrskin Wiki - plain text copy
|
||||
--------------------------------------------------------------------------
|
||||
[[Image(source:/libburn/trunk/cdrskin/doener_150x200_tr.png)]] [http://en.wikipedia.org/wiki/D%C3%B6ner_kebab Doener]
|
||||
|
||||
cdrskin-0.2.3 is the cdrecord compatibility middleware of libburn.
|
||||
'''cdrskin is the cdrecord compatibility middleware of libburn.'''
|
||||
|
||||
Its paragon, cdrecord, is a powerful GPL'ed burn program included in Joerg
|
||||
Schilling's cdrtools. cdrskin strives to be a second source for the services
|
||||
traditionally provided by cdrecord. Currently it does CD-R and CD-RW.
|
||||
Its future ability to burn DVD media depends on the development of libburn.
|
||||
traditionally provided by cdrecord. Currently it does CD-R and CD-RW this way.
|
||||
Overwriteable media DVD-RAM, DVD+RW, DVD-RW, and BD-RE are handled differently
|
||||
than with cdrecord-ProDVD in order to offer TAO-like single track recording.
|
||||
Sequential DVD-R[W], DVD+R, DVD+R DL, BD-R are handled like CD-R[W] with TAO
|
||||
and multi-session. Additionally cdrskin offers cdrecord-ProDVD-like mode DAO
|
||||
with DVD-R[W].
|
||||
|
||||
cdrskin does not contain any bytes copied from cdrecord's sources.
|
||||
Many bytes have been copied from the message output of cdrecord
|
||||
runs, though. The most comprehensive technical overview of cdrskin
|
||||
can be found in cdrskin/README .
|
||||
can be found in [http://libburnia-project.org/browser/libburn/trunk/cdrskin/README?format=txt cdrskin/README].
|
||||
|
||||
About libburn API for burning CD and DVD: http://api.libburnia-project.org
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
cdrskin with CD media fails to match its paragon cdrecord on two major
|
||||
fields: convenient TAO burn mode and multi session.
|
||||
|
||||
cdrskin does not provide DVD burning yet. See advise to use dvd+rw-tools
|
||||
at the end of this text.
|
||||
For yet unsupported media types see the advice to use dvd+rw-tools at
|
||||
the end of this text.
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
About the command line options of cdrskin:
|
||||
|
||||
They are described in detail in [http://scdbackup.sourceforge.net/man_1_cdrskin_devel.html#OPTIONS section OPTIONS] of
|
||||
[http://scdbackup.sourceforge.net/man_1_cdrskin_devel.html man cdrskin]
|
||||
|
||||
There are two families of options: cdrecord-compatible ones and options
|
||||
which are specific to cdrskin. The latter are mostly used to configure
|
||||
cdrskin for its task to emulate cdrecord. There are some, nevertheless,
|
||||
which provide rather exotic unique features of cdrskin.
|
||||
|
||||
The cdrecord-compatible options are listed in the output of
|
||||
|
||||
{{{
|
||||
cdrskin -help
|
||||
}}}
|
||||
where the option "help" has *one* dash. Online: [http://scdbackup.sourceforge.net/cdrskin_help_devel cdrskin -help]
|
||||
|
||||
where the option "help" has *one* dash.
|
||||
For these options you may expect program behavior that is roughly the
|
||||
same as described in original man 1 cdrecord .
|
||||
same as described in original man cdrecord .
|
||||
|
||||
Online: http://cdrecord.berlios.de/old/private/man/cdrecord-2.0.html
|
||||
|
||||
The cdrskin-specific options are listed by
|
||||
|
||||
{{{
|
||||
cdrskin --help
|
||||
}}}
|
||||
where the option "help" has *two* dashes. Online: [http://scdbackup.sourceforge.net/cdrskin__help_devel cdrskin --help]
|
||||
|
||||
where the option "help" has *two* dashes.
|
||||
|
||||
Those have no man page yet. Some are very experimental and should only be
|
||||
used in coordination with the libburn developer team.
|
||||
Some are very experimental and should only be
|
||||
used in coordination with the libburnia developer team.
|
||||
Some are of general user interest, though:
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
@ -56,11 +64,10 @@ Some are of general user interest, though:
|
||||
--devices allows the sysadmin to scan the system for possible drives
|
||||
and displays their detected properties.
|
||||
The drives are listed one per line, with fields:
|
||||
|
||||
libburn-drive-number sysadmin-device-file permissions : vendor type
|
||||
|
||||
0 dev='/dev/sg0' rwrw-- : 'HL-DT-ST' 'DVDRAM GSA-4082B'
|
||||
|
||||
libburn-drive-number, sysadmin-device-file, permissions, vendor, type
|
||||
{{{
|
||||
0 dev='/dev/sr0' rwrw-- : 'HL-DT-ST' 'DVDRAM GSA-4082B'
|
||||
}}}
|
||||
This feature is valuable since cdrskin -scanbus will not give you
|
||||
the device file name and its current permissions.
|
||||
cdrskin will accept of course the proposed dev= option as address
|
||||
@ -74,7 +81,121 @@ has to offer both, r- and w-permission.
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
--fifo_start_empty is a throughput enhancer for unsteady data streams
|
||||
blank=as_needed applies the suitable blanking or formatting to make
|
||||
any supported type of media ready for writing from scratch.
|
||||
If this is not possible, e.g. because the media is written and not
|
||||
re-usable, then the program run fails.
|
||||
|
||||
Option blank= offers several specialized blanking and formatting types,
|
||||
which one may use for particular purposes on DVD-RW, DVD-RAM and BD-RE.
|
||||
(See also below: blank=format_overwrite)
|
||||
The drive offers a list of possible formats by cdrskin option --list_formats.
|
||||
One should aquire MMC background information before making use of them.
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
cdrskin does not only read from and write to optical drives which comply
|
||||
to the MMC standard but also does the same with regular files or block
|
||||
devices other than optical drives.
|
||||
|
||||
Because the power to alter a disk file might be a bad surprise for a
|
||||
traditional user of cdrecord, it is necessary to give option
|
||||
--allow_emulated_drives before an emulated drive may be addressed.
|
||||
Eventually one of the startup files would be a good place for it.
|
||||
See man page, section FILES.
|
||||
|
||||
The addresses of emulated drives begin with the prefix "stdio:".
|
||||
{{{
|
||||
dev=stdio:/tmp/pseudo_drive
|
||||
dev=stdio:/dev/usbstick
|
||||
}}}
|
||||
|
||||
Regular files and block devices behave much like DVD-RAM.
|
||||
|
||||
Other file types may be valid targets for write-only operations.
|
||||
This includes standard output, named pipes, character devices
|
||||
{{{
|
||||
dev=stdio:/dev/fd/1
|
||||
dev=stdio:/tmp/named_pipe
|
||||
dev=stdio:/dev/ptyxy
|
||||
}}}
|
||||
|
||||
These files behave much like blank DVD-R.
|
||||
|
||||
All files used as pseudo-drives have to offer rw-permission.
|
||||
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
The DVD capabilities of cdrskin differ from those of cdrecord-ProDVD. cdrskin
|
||||
offers TAO-like multi-session with DVD-R[W], DVD+R[ DL] and TAO-like single
|
||||
session with overwriteable DVD media. It also offers DAO on DVD-R[W] which is
|
||||
probably the same as the traditional cdrecord-ProDVD write mode.
|
||||
|
||||
Non-cdrecord blank mode blank=format_overwrite brings a DVD-RW
|
||||
disc from its initial profile "Sequential Recording" into profile state
|
||||
"Restricted Overwrite".
|
||||
{{{
|
||||
cdrskin dev=/dev/sr0 -v blank=format_overwrite
|
||||
}}}
|
||||
|
||||
DVD-RAM, DVD+RW, BD-RE and overwriteable DVD-RW appear to cdrskin as blank
|
||||
media which are capable of taking only a single track. This track may be
|
||||
positioned on a 32KiB aligned address, though.
|
||||
{{{
|
||||
cdrskin ... write_start_address=2412m ...
|
||||
}}}
|
||||
|
||||
Non-cdrecord blank mode blank=deformat_sequential brings an overwriteable
|
||||
DVD-RW back into state "Sequential Recording" with the capability of doing
|
||||
multi-session, if the drive is capable of "Incremental Streaming"
|
||||
(MMC feature 21h).
|
||||
|
||||
Used sequential DVD-RW media may be blanked by blank=fast or blank=all which
|
||||
normally both do full blanking. Thus sequential DVD-RW behave much like large
|
||||
CD-RW with possibly more than 99 tracks.
|
||||
|
||||
blank=deformat_sequential does minimal blanking of DVD-RW which usually yields
|
||||
media incapable of "Incremental Streaming".
|
||||
|
||||
Option --prodvd_cli_compatible activates blank=fast and blank=all for
|
||||
overwriteable DVD-RW which normally ignore those two options. It also makes
|
||||
option -multi tolerable with media and write modes which are not suitable for
|
||||
multi-session. (The default behavior of cdrskin deems me to be preferrable.)
|
||||
|
||||
Option --grow_overwriteable_iso gives cdrskin ISO pseudo-multi-session
|
||||
capabilities on DVD-RAM, DVD+RW, BD-RE similar to growisofs.
|
||||
Associated options blank=, -multi, -msinfo and -toc are available in this case.
|
||||
They either pretend a blank media (if there is no ISO 9660 image) or appendable
|
||||
media with a single session and track on it. blank= invalidates ISO images.
|
||||
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
assert_write_lba=<lba> allows to ensure that the start block address which
|
||||
was used with the formatter program (e.g. mkisofs -C) matches the start block
|
||||
address which will be used by the upcoming burn.
|
||||
|
||||
E.g. cdrskin aborts with an error message if
|
||||
{{{
|
||||
assert_write_lba=0
|
||||
}}}
|
||||
is given but an appendable media is to be burned which would start at
|
||||
block 68432.
|
||||
|
||||
|
||||
An ISO-9660 file system image must be prepared according to a particular
|
||||
block address on media. If the prepared address and the real address on media
|
||||
do not match then the filesystem will not be mountable or may even cause system
|
||||
trouble.
|
||||
|
||||
A sequential archive format like afio or star will not necessarily need such
|
||||
a coordination of addresses. It might nevertheless be confusing to a reader
|
||||
if the archive does not start at block 0.
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
fifo_start_at=<num> is a throughput enhancer for unsteady data streams
|
||||
like they are produced by a compressing archiver program when piping to
|
||||
CD on-the-fly. It makes better use of the general property of a FIFO
|
||||
buffer to transport surplus bandwidth into the future. Yep. A time machine.
|
||||
@ -98,10 +219,16 @@ underruns, of course.
|
||||
With a very fat fs=# buffer (128 MB for 12x CD is not unrealistic) this
|
||||
can cause a big delay until burning finally starts and takes its due time.
|
||||
|
||||
--fifo_start_empty makes cdrskin start burning without waiting for the
|
||||
FIFO to be full resp. the data stream to end. It can make use of the
|
||||
seconds spend with drive preparation and lead-in, it risks a few drive
|
||||
buffer underruns at the beginning of burn - but modern drives stand this.
|
||||
fifo_start_at=<num> makes cdrskin start burning after the given number of bytes
|
||||
is read rather than waiting for the FIFO to be completely full resp. the data
|
||||
stream to end. It risks a few drive buffer underruns at the beginning of burn
|
||||
- but modern drives stand this.
|
||||
|
||||
Usage examples:
|
||||
{{{
|
||||
cdrskin ... fs=128m fifo_start_at=20m ...
|
||||
cdrskin ... fifo_start_at=0 ...
|
||||
}}}
|
||||
|
||||
Note: no FIFO can give you better average throughput than the average
|
||||
throughput of the data source and the throughput of the burner.
|
||||
@ -117,21 +244,12 @@ default settings of cdrskin. Possible locations for such settings:
|
||||
|
||||
/etc/opt/cdrskin/rc
|
||||
|
||||
/etc/cdrskin/cdrskin.conf
|
||||
|
||||
$HOME/.cdrskinrc
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
tao_to_sao_tsize=<num> allows the - actually unsupported - cdrecord option
|
||||
-tao and defines a default track size to be used if - as custom with -tao -
|
||||
no option tsize=# is given.
|
||||
|
||||
As in general with cdrskin tsize=# the data source does not have to provide
|
||||
the full annouced amount of data. Missing data will be padded up by 0-bytes.
|
||||
Surplus data is supposed to cause an error, though. The burn will then
|
||||
be a failure in any way.
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
dev_translation=<sep><from><sep><to> may be needed to foist cdrskin to
|
||||
frontend programs of cdrecord which do *not* ask cdrecord -scanbus but
|
||||
which make own assumptions and guesses about cdrecord's device addresses.
|
||||
@ -147,15 +265,15 @@ cdrskin the necessary hint.
|
||||
Example: Your frontend insists in using "0,0,0" and --devices reported
|
||||
dev='/dev/hdc' resp. cdrskin dev=ATA -scanbus reported "1,0,0" then this
|
||||
would be the appropriate translation:
|
||||
|
||||
{{{
|
||||
dev_translation=+0,0,0+/dev/hdc
|
||||
|
||||
}}}
|
||||
The "+" character is a separator to be choosen by you.
|
||||
Currently i am not aware of the need to choose any other than "+"
|
||||
unless you get playful with custom translations like
|
||||
|
||||
{{{
|
||||
dev_translation=-"cd+dvd"-1,0,0
|
||||
|
||||
}}}
|
||||
See http://scdbackup.sourceforge.net/k3b_on_cdrskin.html
|
||||
for an illustrated example with K3b 0.10 .
|
||||
|
||||
@ -163,9 +281,10 @@ for an illustrated example with K3b 0.10 .
|
||||
|
||||
DVD advise:
|
||||
|
||||
For burning of DVD media the cdrskin project currently advises to use
|
||||
Andy Polyakov's dvd+rw-tools which despite their historic name burn
|
||||
for me on above burner: DVD+RW, DVD+R, DVD-RW, DVD-R .
|
||||
For burning of DVD/BD media other than DVD-RAM, DVD+RW, DVD+R, DVD+R DL,
|
||||
DVD-RW, DVD-R, BD-RE, the cdrskin project currently advises to use
|
||||
Andy Polyakov's dvd+rw-tools which despite their historic name are
|
||||
capable of all the media above and more, including BD discs.
|
||||
|
||||
http://fy.chalmers.se/~appro/linux/DVD+RW/tools
|
||||
|
||||
@ -173,24 +292,27 @@ They are not compatible or related to cdrecord resp. cdrecord-ProDVD
|
||||
(now obsoleted by original source cdrtools cdrecord with identical
|
||||
capabilities besides the license key).
|
||||
|
||||
If there is sincere and well motivated interest, the cdrskin project could try
|
||||
to employ growisofs as DVD burning engine. The cdrskin project would prefer to
|
||||
wait for DVD support being included in libburn, though.
|
||||
A very limited and specialized cdrecord-compatibility wrapper for growisofs
|
||||
serves in my project scdbackup. It is not overly hard to make one that serves
|
||||
some very few fixed use cases.
|
||||
|
||||
To my knowledge, Linux kernels 2.6 do write to DVD+RW via block devices as
|
||||
they would write to a traditional tape device. Try old tape archiver
|
||||
commands with addresses like /dev/sr0 or /dev/hdc rather than /dev/mt0 .
|
||||
I have heard rumors that DVD-RW in mode "restricted overwrite" would be
|
||||
block device ready, too. My burner is not a real friend of DVD-RW and
|
||||
in an experiment the burn worked fine - but the result was not identical
|
||||
to the stream sent to the device. I had similar failure with DVD-RAM, too.
|
||||
|
||||
Beware of the impact of a slow block device on overall system i/o buffering.
|
||||
It is wise to curb its input to a speed which it is able to deliver to media.
|
||||
Else your i/o dedicated RAM might buffer a big amount of stream data.
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
Advanced multi-session use cases:
|
||||
|
||||
A special feature of dvd+rw-tools is growing of ISO-9660 filesystems on
|
||||
overwriteable media. This is not the same as multi-session writing of cdrskin
|
||||
with CD media, but retrieves additional information from the existing ISO
|
||||
image and finally manipulates the start sectors of this existing image.
|
||||
|
||||
So, inspired by growisofs, cdrskin can offer DVD multi-session not only with
|
||||
sequential DVD-R[W] and with DVD+R [DL], but also with DVD-RAM, DVD+RW, BD-RE
|
||||
and even regular disk files or block devices other than CD/DVD writers.
|
||||
This is enabled by option --grow_overwriteable_iso.
|
||||
|
||||
The libburnia project provides an integrated ISO-9660 multi-session tool
|
||||
named [wiki:Xorriso xorriso] which tries to go one step beyond
|
||||
growisofs. It uses [wiki:Libburn libburn] , [wiki:Libisofs libisofs]
|
||||
and [wiki:Libisoburn libisoburn].
|
||||
|
||||
See [http://scdbackup.sourceforge.net/man_1_xorriso.html man xorriso].
|
||||
|
||||
--------------------------------------------------------------------------
|
||||
|
||||
|
277
configure.ac
277
configure.ac
@ -1,47 +1,142 @@
|
||||
AC_INIT([libburn], [0.2.3], [http://libburn.pykix.org])
|
||||
AC_INIT([libburn], [1.1.0], [http://libburnia-project.org])
|
||||
AC_PREREQ([2.50])
|
||||
dnl AC_CONFIG_HEADER([config.h])
|
||||
|
||||
AC_CANONICAL_HOST
|
||||
AC_CANONICAL_TARGET
|
||||
|
||||
LIBBURNIA_SET_FLAGS
|
||||
|
||||
AM_INIT_AUTOMAKE([subdir-objects])
|
||||
AC_CONFIG_MACRO_DIR([./])
|
||||
|
||||
dnl A61101 This breaks Linux build (makes 32 bit off_t)
|
||||
dnl http://sourceware.org/autobook/autobook/autobook_96.html says
|
||||
dnl one must include some config.h and this was a pitfall.
|
||||
dnl So why dig the pit at all ?
|
||||
dnl AM_CONFIG_HEADER(config.h)
|
||||
|
||||
dnl Making releases:
|
||||
dnl BURN_MICRO_VERSION += 1;
|
||||
dnl BURN_INTERFACE_AGE += 1;
|
||||
dnl BURN_BINARY_AGE += 1;
|
||||
dnl if any functions have been added, set BURN_INTERFACE_AGE to 0.
|
||||
dnl if backwards compatibility has been broken,
|
||||
dnl set BURN_BINARY_AGE and BURN_INTERFACE_AGE to 0.
|
||||
dnl Notes by ts A71207 - B10409 :
|
||||
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
|
||||
BURN_MAJOR_VERSION=0
|
||||
BURN_MINOR_VERSION=2
|
||||
BURN_MICRO_VERSION=3
|
||||
BURN_INTERFACE_AGE=0
|
||||
BURN_BINARY_AGE=0
|
||||
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 On Linux the name of the dynamic library will be
|
||||
dnl libburn.so.$SONAME.$AGE.$REV
|
||||
dnl In the terminology of this file:
|
||||
dnl CURRENT = LT_CURRENT
|
||||
dnl AGE = LT_AGE
|
||||
dnl REVISION= LT_REVISION
|
||||
dnl
|
||||
dnl Beginning with libburn-0.4.1 a rectified counting was introduced as
|
||||
dnl CURRENT=10, REVISION=1, AGE=6
|
||||
dnl This rectification declared that version to be binary compatible up
|
||||
dnl from libburn-0.3.4.
|
||||
dnl Real compatibility was given since libburn-0.3.2.
|
||||
dnl Beware of libburn-0.2.6 which had SONAME=6 and is not binary compatible.
|
||||
dnl Applications for libburn-0.2 to libburn-0.3.1 need recompilation but no
|
||||
dnl source code changes.
|
||||
dnl
|
||||
dnl Neatly versioned stable releases meanwhile:
|
||||
dnl 0.4.2 = libburn.so.4.7.0
|
||||
dnl 0.4.4 = libburn.so.4.9.0
|
||||
dnl 0.4.6 = libburn.so.4.11.0
|
||||
dnl 0.4.8 = libburn.so.4.13.0
|
||||
dnl 0.5.0 = libburn.so.4.15.0
|
||||
dnl 0.5.2 = libburn.so.4.17.0
|
||||
dnl 0.5.4 = libburn.so.4.19.0
|
||||
dnl 0.5.6 = libburn.so.4.21.0
|
||||
dnl 0.5.8 = libburn.so.4.23.0
|
||||
dnl 0.6.0 = libburn.so.4.25.0
|
||||
dnl 0.6.2 = libburn.so.4.27.0
|
||||
dnl 0.6.4 = libburn.so.4.29.0
|
||||
dnl 0.6.6 = libburn.so.4.31.0
|
||||
dnl 0.6.8 = libburn.so.4.33.0
|
||||
dnl 0.7.0 = libburn.so.4.35.0
|
||||
dnl 0.7.2 = libburn.so.4.37.0
|
||||
dnl 0.7.4 = libburn.so.4.39.0
|
||||
dnl 0.7.6 = libburn.so.4.41.0
|
||||
dnl 0.7.8 = libburn.so.4.43.0
|
||||
dnl 0.8.0 = libburn.so.4.45.0
|
||||
dnl 0.8.2 = libburn.so.4.47.0
|
||||
dnl 0.8.4 = libburn.so.4.49.0
|
||||
dnl 0.8.6 = libburn.so.4.51.0
|
||||
dnl 0.8.8 = libburn.so.4.53.0
|
||||
dnl 0.9.0 = libburn.so.4.55.0
|
||||
dnl 1.0.0 = libburn.so.4.57.0
|
||||
dnl 1.0.2 = libburn.so.4.59.0
|
||||
dnl 1.0.4 = libburn.so.4.61.0
|
||||
dnl 1.0.6 = libburn.so.4.63.0
|
||||
dnl 1.1.0 = libburn.so.4.65.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=1
|
||||
BURN_MINOR_VERSION=1
|
||||
BURN_MICRO_VERSION=0
|
||||
BURN_VERSION=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION
|
||||
|
||||
AC_SUBST(BURN_MAJOR_VERSION)
|
||||
AC_SUBST(BURN_MINOR_VERSION)
|
||||
AC_SUBST(BURN_MICRO_VERSION)
|
||||
AC_SUBST(BURN_INTERFACE_AGE)
|
||||
AC_SUBST(BURN_BINARY_AGE)
|
||||
AC_SUBST(BURN_VERSION)
|
||||
|
||||
dnl Libtool versioning
|
||||
LT_RELEASE=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION
|
||||
LT_CURRENT=`expr $BURN_MICRO_VERSION - $BURN_INTERFACE_AGE`
|
||||
LT_REVISION=$BURN_INTERFACE_AGE
|
||||
LT_AGE=`expr $BURN_BINARY_AGE - $BURN_INTERFACE_AGE`
|
||||
LT_RELEASE=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION
|
||||
dnl
|
||||
dnl This is the release version libburn-1.1.0
|
||||
dnl ### This is the development version after above release version
|
||||
dnl LT_CURRENT++, LT_AGE++ has not yet happened.
|
||||
dnl ### LT_CURRENT++, LT_AGE++ has happened meanwhile.
|
||||
dnl
|
||||
dnl SONAME = 69 - 65 = 4 . Linux library name = libburn.so.4.65.0
|
||||
LT_CURRENT=69
|
||||
LT_AGE=65
|
||||
LT_REVISION=0
|
||||
LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
|
||||
|
||||
AC_SUBST(LT_RELEASE)
|
||||
@ -50,6 +145,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
|
||||
|
||||
@ -63,6 +164,7 @@ AC_C_BIGENDIAN
|
||||
dnl Large file support
|
||||
AC_SYS_LARGEFILE
|
||||
AC_FUNC_FSEEKO
|
||||
AC_CHECK_FUNC([fseeko])
|
||||
if test ! $ac_cv_func_fseeko; then
|
||||
AC_ERROR([Libburn requires largefile support.])
|
||||
fi
|
||||
@ -75,19 +177,113 @@ AC_PROG_INSTALL
|
||||
|
||||
AC_CHECK_HEADERS()
|
||||
|
||||
AC_CHECK_MEMBER([struct tm.tm_gmtoff],
|
||||
[AC_DEFINE(HAVE_TM_GMTOFF, 1,
|
||||
[Define this if tm structure includes a tm_gmtoff entry.])],
|
||||
,
|
||||
[#include <time.h>])
|
||||
|
||||
THREAD_LIBS=-lpthread
|
||||
AC_SUBST(THREAD_LIBS)
|
||||
|
||||
TARGET_SHIZZLE
|
||||
AC_SUBST(ARCH)
|
||||
AC_SUBST(LIBBURNIA_PKGCONFDIR)
|
||||
AC_SUBST(LIBBURN_ARCH_LIBS)
|
||||
|
||||
dnl ts A90303
|
||||
dnl Check the preconditions for using statvfs() in sg-dummy
|
||||
dnl (sg-linux and sg-freebsd use statvfs() unconditionally)
|
||||
STATVFS_DEF=-DLibburn_os_has_statvfS
|
||||
AC_CHECK_HEADER(sys/statvfs.h, X=, STATVFS_DEF=)
|
||||
AC_CHECK_FUNC([statvfs], X=, STATVFS_DEF=)
|
||||
dnl If this would be done more specifically in Makefile.am
|
||||
dnl via libburn_libburn_la_CFLAGS then undesired .o file names would emerge
|
||||
CFLAGS="$STATVFS_DEF $CFLAGS"
|
||||
|
||||
dnl ts A91122
|
||||
AC_ARG_ENABLE(track-src-odirect,
|
||||
[ --enable-track-src-odirect Enable use of O_DIRECT with track input, default=no],
|
||||
, enable_track_src_odirect=no)
|
||||
if test x$enable_track_src_odirect = xyes; then
|
||||
LIBBURN_O_DIRECT_DEF="-DLibburn_read_o_direcT"
|
||||
echo "enabled use of O_DIRECT with track input"
|
||||
else
|
||||
LIBBURN_O_DIRECT_DEF=
|
||||
echo "disabled use of O_DIRECT with track input"
|
||||
fi
|
||||
dnl Avoid the need for libburn_libburn_la_CFLAGS in Makefile.am (ugly .o names)
|
||||
dnl ### AC_SUBST(LIBBURN_O_DIRECT_DEF)
|
||||
CFLAGS="$LIBBURN_O_DIRECT_DEF $CFLAGS"
|
||||
|
||||
dnl ts A91116
|
||||
AC_ARG_ENABLE(dvd-obs-64k,
|
||||
[ --enable-dvd-obs-64k 64 KB default size for DVD/BD writing, default=no],
|
||||
, enable_dvd_obs_64k=no)
|
||||
if test x$enable_dvd_obs_64k = xyes; then
|
||||
LIBBURN_DVD_OBS_64K="-DLibburn_dvd_obs_default_64K"
|
||||
echo "enabled write size default 64 KB on DVD and BD"
|
||||
else
|
||||
LIBBURN_DVD_OBS_64K=
|
||||
echo "disabled write size default 64 KB on DVD and BD"
|
||||
fi
|
||||
CFLAGS="$LIBBURN_DVD_OBS_64K $CFLAGS"
|
||||
|
||||
dnl ts A91218
|
||||
AC_ARG_ENABLE(libcdio,
|
||||
[ --enable-libcdio Enable EXPERIMENTAL use of libcdio as system adapter, default=no],
|
||||
, enable_libcdio=no)
|
||||
if test x$enable_libcdio = xyes; then
|
||||
dnl Check whether there is libcdio-devel and libcdio-runtime.
|
||||
dnl If not, erase this macro
|
||||
LIBCDIO_DEF="-DLibburn_use_libcdiO"
|
||||
dnl The empty yes case obviously causes -lcdio to be linked
|
||||
AC_CHECK_HEADER(cdio/cdio.h, AC_CHECK_LIB(cdio, mmc_last_cmd_sense, , LIBCDIO_DEF= ), LIBCDIO_DEF= )
|
||||
else
|
||||
LIBCDIO_DEF=
|
||||
fi
|
||||
if test x$LIBCDIO_DEF = x
|
||||
then
|
||||
if test x$enable_libcdio = xyes
|
||||
then
|
||||
echo "WARNING: could not enable use of libcdio as system adapter"
|
||||
fi
|
||||
else
|
||||
echo "enabled EXPERIMENTAL use of libcdio as system adapter"
|
||||
CFLAGS="$LIBCDIO_DEF $CFLAGS"
|
||||
|
||||
LIBCDIO_REQUIRED=0.83
|
||||
PKG_CHECK_MODULES(LIBCDIO, libcdio >= $LIBCDIO_REQUIRED)
|
||||
|
||||
fi
|
||||
|
||||
dnl ts B00704
|
||||
# Library versioning normally serves a complex purpose.
|
||||
# Since libburn obeys strict ABI backward compatibility, it needs only the
|
||||
# simple feature to declare function names "global:" or "local:". Only the
|
||||
# global ones are visible to applications at library load time.
|
||||
AC_ARG_ENABLE(versioned-libs,
|
||||
[ --enable-versioned-libs Enable strict symbol encapsulation , default=yes],
|
||||
, enable_versioned_libs=yes)
|
||||
if test x$enable_versioned_libs = xyes; then
|
||||
vers_libs_test=no
|
||||
LIBBURN_ASSERT_VERS_LIBS
|
||||
if test x$vers_libs_test = xno
|
||||
then
|
||||
echo "disabled strict symbol encapsulation (test failed)"
|
||||
else
|
||||
echo "enabled strict symbol encapsulation"
|
||||
fi
|
||||
else
|
||||
echo "disabled strict symbol encapsulation"
|
||||
fi
|
||||
|
||||
AC_ARG_ENABLE(ldconfig-at-install,
|
||||
[ --enable-ldconfig-at-install On GNU/Linux run ldconfig, default=yes],
|
||||
, ldconfig_at_install=yes)
|
||||
if test x$ldconfig_at_install = xyes; then
|
||||
dummy=dummy
|
||||
else
|
||||
LIBBURNIA_LDCONFIG_CMD="echo 'NOTE: ldconfig is disabled. If needed, configure manually for:'"
|
||||
echo "disabled run of ldconfig during installation on GNU/Linux"
|
||||
fi
|
||||
AC_SUBST(LIBBURNIA_LDCONFIG_CMD)
|
||||
|
||||
|
||||
dnl Add compiler-specific flags
|
||||
|
||||
dnl See if the user wants aggressive optimizations of the code
|
||||
@ -96,22 +292,27 @@ AC_ARG_ENABLE(debug,
|
||||
, enable_debug=yes)
|
||||
if test x$enable_debug != xyes; then
|
||||
if test x$GCC = xyes; then
|
||||
CFLAGS="$CFLAGS -O3"
|
||||
CFLAGS="$CFLAGS -fexpensive-optimizations"
|
||||
CFLAGS="-O3 $CFLAGS"
|
||||
CFLAGS="-fexpensive-optimizations $CFLAGS"
|
||||
fi
|
||||
CFLAGS="$CFLAGS -DNDEBUG"
|
||||
CFLAGS="-DNDEBUG $CFLAGS"
|
||||
else
|
||||
if test x$GCC = xyes; then
|
||||
CFLAGS="$CFLAGS -g -pedantic -Wall"
|
||||
CFLAGS="-g -pedantic -Wall -Wextra -Wno-unused-parameter $CFLAGS"
|
||||
fi
|
||||
CFLAGS="$CFLAGS -DDEBUG"
|
||||
CFLAGS="-DDEBUG $CFLAGS"
|
||||
fi
|
||||
|
||||
dnl Determine target directory for libburn-*.pc
|
||||
dnl Important: Must be performed _after_ TARGET_SHIZZLE
|
||||
dnl
|
||||
LIBBURNIA_SET_PKGCONFIG
|
||||
|
||||
|
||||
AC_CONFIG_FILES([
|
||||
Makefile
|
||||
doc/doxygen.conf
|
||||
version.h
|
||||
libburn-1.pc
|
||||
libisofs-1.pc
|
||||
])
|
||||
AC_OUTPUT
|
||||
|
127
doc/comments
127
doc/comments
@ -5,61 +5,46 @@
|
||||
|
||||
@section intro Introduction
|
||||
|
||||
Libburn is an open-source library for reading, mastering and writing
|
||||
optical discs. For now this means only CD-R and CD-RW.
|
||||
Libburnia is an open-source project for reading, mastering and writing
|
||||
optical discs. This page is about its capability to handle optical media.
|
||||
For now this means CD-R, CD-RW, DVD-RAM, DVD+RW, DVD+R, DVD+R/DL, DVD-RW,
|
||||
DVD-R, DVD-R/DL, BD-R, BD-RE.
|
||||
|
||||
The project comprises of several more or less interdependent parts which
|
||||
together strive to be a usable foundation for application development.
|
||||
These are libraries, language bindings, and middleware binaries which emulate
|
||||
classical (and valuable) Linux tools.
|
||||
Our scope is currently Linux 2.4 and 2.6, or FreeBSD, or Solaris . For ports
|
||||
to other systems we would need : login on a development machine resp.
|
||||
an OS ithat is installable on an AMD 64-bit PC, advise from a system person
|
||||
about the equivalent of Linux sg or FreeBSD CAM, volunteers for testing of
|
||||
realistic use cases.
|
||||
|
||||
Our scope is currently Linux 2.4 and 2.6 and we will have a hard time to widen
|
||||
this for now, because of our history. The project could need advise from or
|
||||
membership of skilled kernel people and people who know how to talk CD/DVD
|
||||
drives into doing things.
|
||||
libburn is the library by which preformatted data get onto optical media.
|
||||
Its code is independent of cdrecord. Its DVD capabilities are learned from
|
||||
studying the code of dvd+rw-tools and MMC-5 specs. No code but only the pure
|
||||
SCSI knowledge has been taken from dvd+rw-tools, though.
|
||||
|
||||
We do have a workable code base for burning data CDs, though. The burn API is
|
||||
quite comprehensively documented and can be used to build a presentable
|
||||
application.
|
||||
We do have a functional binary which emulates parts of cdrecord in order to
|
||||
prove that usability, and in order to allow you to explore libburn's scope
|
||||
by help of existing cdrecord frontends.
|
||||
cdrskin is a limited cdrecord compatibility wrapper for libburn.
|
||||
cdrecord is a powerful GPL'ed burn program included in Joerg Schilling's
|
||||
cdrtools. cdrskin strives to be a second source for the services traditionally
|
||||
provided by cdrecord. Additionally it provides libburn's DVD/BD capabilities,
|
||||
where only -sao is compatible with cdrecord.
|
||||
cdrskin does not contain any bytes copied from cdrecord's sources.
|
||||
Many bytes have been copied from the message output of cdrecord runs, though.
|
||||
See cdrskin/README for more.
|
||||
|
||||
@subsection components The project components (list subject to growth, hopefully):
|
||||
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.
|
||||
|
||||
- libburn is the library by which preformatted data get onto optical media.
|
||||
It uses either /dev/sgN (e.g. on kernel 2.4 with ide-scsi) or
|
||||
/dev/hdX (e.g. on kernel 2.6).
|
||||
libburn is the foundation of our cdrecord emulation.
|
||||
|
||||
- libisofs is the library to pack up hard disk files and directories into a
|
||||
ISO 9660 disk image. This may then be brought to CD via libburn.
|
||||
libisofs is to be the foundation of our upcoming mkisofs emulation.
|
||||
|
||||
- cdrskin is a limited cdrecord compatibility wrapper for libburn.
|
||||
cdrecord is a powerful GPL'ed burn program included in Joerg
|
||||
Schilling's cdrtools. cdrskin strives to be a second source for
|
||||
the services traditionally provided by cdrecord.
|
||||
cdrskin does not contain any bytes copied from cdrecord's sources.
|
||||
Many bytes have been copied from the message output of cdrecord
|
||||
runs, though.
|
||||
See cdrskin/README for more.
|
||||
|
||||
- "test" is a collection of application gestures and examples given by the
|
||||
authors of the library features. The main API example of libburn
|
||||
is named test/libburner.c .
|
||||
Explore these examples if you look for inspiration.
|
||||
|
||||
We plan to be a responsive upstream. Bear with us.
|
||||
SONAME:
|
||||
libburn.so.4 (since 0.3.4, March 2007),
|
||||
|
||||
|
||||
@section using Using the libraries
|
||||
@section using Using libburn
|
||||
|
||||
Our build system is based on autotools.
|
||||
User experience tells us that you will need at least autotools version 1.7.
|
||||
|
||||
To build libburn and its subprojects it should be sufficient to go into
|
||||
its toplevel directory and execute
|
||||
To build libburn and its companion applications go into its toplevel directory
|
||||
and execute
|
||||
|
||||
- ./bootstrap (needed if you downloaded from SVN)
|
||||
|
||||
@ -71,49 +56,59 @@ To make the libraries accessible for running resp. developing applications
|
||||
|
||||
- make install
|
||||
|
||||
Both libraries are written in C language and get built by autotools.
|
||||
Thus we expect them to be useable by a wide range of Linux-implemented
|
||||
languages and development tools.
|
||||
|
||||
|
||||
@section libburner Libburner
|
||||
|
||||
libburner is a minimal demo application for the library libburn
|
||||
(see: libburn/libburn.h) as provided on http://libburn.pykix.org .
|
||||
It can list the available devices, can blank a CD-RW and
|
||||
can burn to CD-R or CD-RW.
|
||||
(see: libburn/libburn.h) as provided on http://libburnia-project.org .
|
||||
It can list the available devices, can burn to recordable CD, DVD, or BD,
|
||||
can blank a CD-RW or DVD-RW, and can format unformatted DVD-RW, BD-R, or BD-RE.
|
||||
|
||||
It's main purpose, nevertheless, is to show you how to use libburn and also
|
||||
to serve the libburn team as reference application. libburner does indeed
|
||||
define the standard way how above three gestures can be implemented and
|
||||
stay upward compatible for a good while.
|
||||
to serve the libburnia team as reference application. libburner does indeed
|
||||
define the standard way how above gestures can be implemented and stay upward
|
||||
compatible for a good while.
|
||||
|
||||
@subsection libburner-help Libburner --help
|
||||
<pre>
|
||||
Usage: test/libburner
|
||||
[--drive <address>|<driveno>|"-"]
|
||||
[--blank_fast|--blank_full] [--audio]
|
||||
[--try_to_simulate] [--stdin_size <bytes>]
|
||||
[<one or more imagefiles>|"-"]
|
||||
[--drive address|driveno|"-"] [--audio]
|
||||
[--blank_fast|--blank_full|--format] [--try_to_simulate]
|
||||
[--multi] [one or more imagefiles|"-"]
|
||||
Examples
|
||||
A bus scan (needs rw-permissions to see a drive):
|
||||
test/libburner --drive -
|
||||
Burn a file to drive chosen by number:
|
||||
test/libburner --drive 0 my_image_file
|
||||
Burn a file to drive chosen by persistent address:
|
||||
Burn a file to drive chosen by number, leave appendable:
|
||||
test/libburner --drive 0 --multi my_image_file
|
||||
Burn a file to drive chosen by persistent address, close:
|
||||
test/libburner --drive /dev/hdc my_image_file
|
||||
Blank a used CD-RW (is combinable with burning in one run):
|
||||
test/libburner --drive /dev/hdc --blank_fast
|
||||
Burn two audio tracks
|
||||
Blank a used DVD-RW (is combinable with burning in one run):
|
||||
test/libburner --drive /dev/hdc --blank_full
|
||||
Format a DVD-RW, BD-RE or BD-R:
|
||||
test/libburner --drive /dev/hdc --format
|
||||
Burn two audio tracks (to CD only):
|
||||
lame --decode -t /path/to/track1.mp3 track1.cd
|
||||
test/dewav /path/to/track2.wav -o track2.cd
|
||||
test/libburner --drive /dev/hdc --audio track1.cd track2.cd
|
||||
Burn a compressed afio archive on-the-fly, pad up to 700 MB:
|
||||
Burn a compressed afio archive on-the-fly:
|
||||
( cd my_directory ; find . -print | afio -oZ - ) | \
|
||||
test/libburner --drive /dev/hdc --stdin_size 734003200 -
|
||||
To be read from *not mounted* CD via: afio -tvZ /dev/hdc
|
||||
Program tar would need a clean EOF which our padded CD cannot deliver.
|
||||
test/libburner --drive /dev/hdc -
|
||||
To be read from *not mounted* media via: afio -tvZ /dev/hdc
|
||||
</pre>
|
||||
libburner has two companions, telltoc and dewav, which help to perform some
|
||||
peripheral tasks of burning.
|
||||
|
||||
telltoc prints a table of content (sessions, tracks and leadouts), it tells
|
||||
about type and state of media, and also is able to provide the necessary
|
||||
multi-session information for program mkisofs option -C. Especially helpful
|
||||
are its predictions with "Write multi" and "Write modes" where availability
|
||||
of "TAO" indicates that tracks of unpredicted length can be written.
|
||||
See: test/telltoc --help.
|
||||
|
||||
dewav extracts raw byte-swapped audio data from files of format .wav (MS WAVE)
|
||||
or .au (SUN Audio). See example in libburner --help.
|
||||
|
||||
@subsection libburner-source Sourceode of libburner
|
||||
|
||||
|
@ -1,121 +0,0 @@
|
||||
/**
|
||||
@author Mario Danic, Thomas Schmitt
|
||||
|
||||
@mainpage Libburn Documentation Index
|
||||
|
||||
@section intro Introduction
|
||||
|
||||
Libburn is an open-source library for reading, mastering and writing
|
||||
optical discs. For now this means only CD-R and CD-RW.
|
||||
|
||||
The project comprises of several more or less interdependent parts which
|
||||
together strive to be a usable foundation for application development.
|
||||
These are libraries, language bindings, and middleware binaries which emulate
|
||||
classical (and valuable) Linux tools.
|
||||
|
||||
Our scope is currently Linux 2.4 and 2.6 and we will have a hard time to widen
|
||||
this for now, because of our history. The project could need advise from or
|
||||
membership of skilled kernel people and people who know how to talk CD/DVD
|
||||
drives into doing things.
|
||||
|
||||
We do have a workable code base for burning data CDs, though. The burn API is
|
||||
quite comprehensively documented and can be used to build a presentable
|
||||
application.
|
||||
We do have a functional binary which emulates parts of cdrecord in order to
|
||||
prove that usability, and in order to allow you to explore libburn's scope
|
||||
by help of existing cdrecord frontends.
|
||||
|
||||
@subsection components The project components (list subject to growth, hopefully):
|
||||
|
||||
- libburn is the library by which preformatted data get onto optical media.
|
||||
It uses either /dev/sgN (e.g. on kernel 2.4 with ide-scsi) or
|
||||
/dev/hdX (e.g. on kernel 2.6).
|
||||
libburn is the foundation of our cdrecord emulation.
|
||||
|
||||
- libisofs is the library to pack up hard disk files and directories into a
|
||||
ISO 9660 disk image. This may then be brought to CD via libburn.
|
||||
libisofs is to be the foundation of our upcoming mkisofs emulation.
|
||||
|
||||
- cdrskin is a limited cdrecord compatibility wrapper for libburn.
|
||||
cdrecord is a powerful GPL'ed burn program included in Joerg
|
||||
Schilling's cdrtools. cdrskin strives to be a second source for
|
||||
the services traditionally provided by cdrecord.
|
||||
cdrskin does not contain any bytes copied from cdrecord's sources.
|
||||
Many bytes have been copied from the message output of cdrecord
|
||||
runs, though.
|
||||
See cdrskin/README for more.
|
||||
|
||||
- "test" is a collection of application gestures and examples given by the
|
||||
authors of the library features. The main API example of libburn
|
||||
is named test/libburner.c .
|
||||
Explore these examples if you look for inspiration.
|
||||
|
||||
We plan to be a responsive upstream. Bear with us.
|
||||
|
||||
|
||||
@section using Using the libraries
|
||||
|
||||
Our build system is based on autotools.
|
||||
User experience tells us that you will need at least autotools version 1.7.
|
||||
|
||||
To build libburn and its subprojects it should be sufficient to go into
|
||||
its toplevel directory and execute
|
||||
|
||||
- ./bootstrap (needed if you downloaded from SVN)
|
||||
|
||||
- ./configure
|
||||
|
||||
- make
|
||||
|
||||
To make the libraries accessible for running resp. developing applications
|
||||
|
||||
- make install
|
||||
|
||||
Both libraries are written in C language and get built by autotools.
|
||||
Thus we expect them to be useable by a wide range of Linux-implemented
|
||||
languages and development tools.
|
||||
|
||||
|
||||
@section libburner Libburner
|
||||
|
||||
libburner is a minimal demo application for the library libburn
|
||||
(see: libburn/libburn.h) as provided on http://libburn.pykix.org .
|
||||
It can list the available devices, can blank a CD-RW and
|
||||
can burn to CD-R or CD-RW.
|
||||
|
||||
It's main purpose, nevertheless, is to show you how to use libburn and also
|
||||
to serve the libburn team as reference application. libburner does indeed
|
||||
define the standard way how above three gestures can be implemented and
|
||||
stay upward compatible for a good while.
|
||||
|
||||
@subsection libburner-help Libburner --help
|
||||
<pre>
|
||||
Usage: test/libburner
|
||||
[--drive <address>|<driveno>|"-"]
|
||||
[--verbose <level>] [--blank_fast|--blank_full]
|
||||
[--burn_for_real|--try_to_simulate] [--stdin_size <bytes>]
|
||||
[<imagefile>|"-"]
|
||||
Examples
|
||||
A bus scan (needs rw-permissions to see a drive):
|
||||
test/libburner --drive -
|
||||
Burn a file to drive chosen by number:
|
||||
test/libburner --drive 0 --burn_for_real my_image_file
|
||||
Burn a file to drive chosen by persistent address:
|
||||
test/libburner --drive /dev/hdc --burn_for_real my_image_file
|
||||
Blank a used CD-RW (is combinable with burning in one run):
|
||||
test/libburner --drive 0 --blank_fast
|
||||
Burn a compressed afio archive on-the-fly, pad up to 700 MB:
|
||||
( cd my_directory ; find . -print | afio -oZ - ) | \
|
||||
test/libburner --drive /dev/hdc --burn_for_real --stdin_size 734003200 -
|
||||
To be read from *not mounted* CD via:
|
||||
afio -tvZ /dev/hdc
|
||||
Program tar would need a clean EOF which our padded CD cannot deliver.
|
||||
</pre>
|
||||
|
||||
@subsection libburner-source Sourceode of libburner
|
||||
|
||||
Click on blue names of functions, structures, variables, etc in oder to
|
||||
get to the according specs of libburn API or libburner sourcecode.
|
||||
|
||||
@include libburner.c
|
||||
*/
|
1409
doc/cookbook.txt
Normal file
1409
doc/cookbook.txt
Normal file
File diff suppressed because it is too large
Load Diff
388
doc/ddlp.txt
Normal file
388
doc/ddlp.txt
Normal file
@ -0,0 +1,388 @@
|
||||
-------------------------------------------------------------------------------
|
||||
|
||||
Users of modern desktop Linux installations report misburns with CD/DVD
|
||||
recording due to concurrency problems.
|
||||
|
||||
This text describes two locking protocols which have been developed by our
|
||||
best possible effort. But finally they rather serve as repelling example of
|
||||
what would be needed in user space to achieve an insufficient partial solution.
|
||||
|
||||
Ted Ts'o was so friendly to help as critic with his own use cases. It turned
|
||||
out that we cannot imagine a way in user space how to cover reliably the needs
|
||||
of callers of libblkid and the needs of our burn programs.
|
||||
|
||||
-------------------------------------------------------------------------------
|
||||
Content:
|
||||
|
||||
The "Delicate Device Locking Protocol" shall demonstrate our sincere
|
||||
consideration of the problem.
|
||||
|
||||
"What are the Stumble Stones ?" lists reasons why the effort finally failed.
|
||||
|
||||
-----------------------------------------------------------------------------
|
||||
|
||||
|
||||
Delicate Device Locking Protocol
|
||||
(a joint sub project of cdrkit and libburnia)
|
||||
(contact: scdbackup@gmx.net )
|
||||
|
||||
Our projects provide programs which allow recording of data on CD or DVD.
|
||||
We encounter an increasing number of bug reports about spoiled burn runs and
|
||||
wasted media which obviously have one common cause: interference by other
|
||||
programs which access the drive's device files.
|
||||
There is some riddling about which gestures exactly are dangerous for
|
||||
ongoing recordings or can cause weirdly misformatted drive replies to MMC
|
||||
commands.
|
||||
We do know, nevertheless, that these effects do not occur if no other program
|
||||
accesses a device file of the drive while our programs use it.
|
||||
|
||||
DDLP shall help to avoid collisions between programs in the process of
|
||||
recording to a CD or DVD drive and other programs which access that drive.
|
||||
The protocol intends to provide advisory locking. So any good-willing program
|
||||
has to take some extra precautions to participate.
|
||||
|
||||
If a program does not feel vulnerable to disturbance, then the precautions
|
||||
impose much less effort than if the program feels the need for protection.
|
||||
|
||||
Two locking strategies are specified:
|
||||
DDLP-A operates on device files only. It is very Linux specific.
|
||||
DDLP-B adds proxy lock files, inspired by FHS /var/lock standard.
|
||||
|
||||
|
||||
DDLP-A
|
||||
|
||||
This protocol relies on the hardly documented feature open(O_EXCL | O_RDWR)
|
||||
with Linux device files and on POSIX compliant fcntl(F_SETLK).
|
||||
|
||||
Other than the original meaning of O_EXCL with creating regular files, the
|
||||
effect on device files is mutual exclusion of access. I.e. if one
|
||||
filedescriptor is open on that combination of major-minor device number, then
|
||||
no other open(O_EXCL) will succeed. But open() without O_EXCL would succeed.
|
||||
So this is advisory and exclusive locking.
|
||||
With kernel 2.6 it seems to work on all device drivers which might get used
|
||||
to access a CD/DVD drive.
|
||||
|
||||
The vulnerable programs shall not start their operation before they occupied a
|
||||
wide collection of drive representations.
|
||||
Non-vulnerable programs shall take care to detect the occupation of _one_ such
|
||||
representation.
|
||||
|
||||
So for Friendly Programs
|
||||
|
||||
A program which does not feel vulnerable to disturbance is urged to access
|
||||
CD/DVD drives by opening a file descriptor which will uphold the lock
|
||||
as long as it does not get closed. There are two alternative ways to achieve
|
||||
this.
|
||||
Very reliable is
|
||||
|
||||
open( some_path , O_EXCL | ...)
|
||||
|
||||
But O_EXCL imposes restrictions and interferences:
|
||||
- O_EXCL | O_RDONLY does not succeed with /dev/sg* !
|
||||
- O_EXCL cannot provide shared locks for programs which only want to lock
|
||||
against burn programs but not against their own peers.
|
||||
- O_EXCL keeps from obtaining information by harmless activities.
|
||||
- O_EXCL already has a meaning with devices which are mounted as filesystems.
|
||||
This priority meaning is more liberal than the one needed for CD/DV recording
|
||||
protection.
|
||||
|
||||
So it may be necessary to use a cautious open() without O_EXCL and to aquire
|
||||
a POSIX lock via fcntl(). "Cautious" means to add O_NDELAY to the flags of
|
||||
open(), because this is declared to avoid side effects within open().
|
||||
|
||||
With this gesture it is important to use the paths expected by our burn
|
||||
programs: /dev/sr[0..255] /dev/scd[0..255] /dev/sg[0..255] /dev/hd[a..z]
|
||||
because fcntl(F_SETLK) does not lock the device but only a device-inode.
|
||||
|
||||
std_path = one of the standard device files:
|
||||
/dev/sr[0..255] /dev/scd[0..255] /dev/sg[0..255] /dev/hd[a..z]
|
||||
or a symbolic link pointing to one of them.
|
||||
open( std_path , ... | O_NDELAY)
|
||||
fcntl(F_SETLK) and close() on failure
|
||||
... eventually disable O_NDELAY by fcntl(F_SETFL) ...
|
||||
|
||||
There is a pitfall mentioned in man 2 fcntl :
|
||||
"locks are automatically released [...] if it closes any file descriptor
|
||||
referring to a file on which locks are held. This is bad [...]"
|
||||
So you may have to re-lock after some temporary fd got closed.
|
||||
|
||||
|
||||
Vulnerable Programs
|
||||
|
||||
For programs which do feel vulnerable, O_EXCL would suffice for the /dev/hd*
|
||||
device file family and their driver. But USB and SATA recorders appear with
|
||||
at least two different major-minor combinations simultaneously.
|
||||
One as /dev/sr* alias /dev/scd*, the other as /dev/sg*.
|
||||
The same is true for ide-scsi or recorders attached to SCSI controllers.
|
||||
|
||||
So, in order to lock any access to the recorder, one has to open(O_EXCL)
|
||||
not only the device file that is intended for accessing the recorder but also
|
||||
a device file of any other major-minor representation of the recorder.
|
||||
This is done via the SCSI address parameter vector (Host,Channel,Id,Lun)
|
||||
and a search on standard device file paths /dev/sr* /dev/scd* /dev/sg*.
|
||||
In this text the alternative device representations are called "siblings".
|
||||
|
||||
For finding them, it is necessary to apply open() to many device files which
|
||||
might be occupied by delicate operations. On the other hand it is very
|
||||
important to occupy all reasonable representations of the drive.
|
||||
So the reading of the (Host,Channel,Id,Lun) parameters demands an
|
||||
open(O_RDONLY | O_NDELAY) _without_ fcntl() in order to find the outmost
|
||||
number of representations among the standard device files. Only ioctls
|
||||
SCSI_IOCTL_GET_IDLUN and SCSI_IOCTL_GET_BUS_NUMBER are applied.
|
||||
Hopefully this gesture is unable to cause harmful side effects on kernel 2.6.
|
||||
|
||||
At least one file of each class sr, scd and sg should be found to regard
|
||||
the occupation as satisfying. Thus corresponding sr-scd-sg triplets should have
|
||||
matching ownerships and access permissions.
|
||||
One will have to help the sysadmins to find those triplets.
|
||||
|
||||
A spicy detail is that sr and scd may be distinct device files for the same
|
||||
major-minor combination. In this case fcntl() locks on both are needed
|
||||
but O_EXCL can only be applied to one of them.
|
||||
|
||||
|
||||
An open and free implementation ddlpa.[ch] is provided as
|
||||
http://libburnia.pykix.org/browser/libburn/trunk/libburn/ddlpa.h?format=txt
|
||||
http://libburnia.pykix.org/browser/libburn/trunk/libburn/ddlpa.c?format=txt
|
||||
The current version of this text is
|
||||
http://libburnia.pykix.org/browser/libburn/trunk/doc/ddlp.txt?format=txt
|
||||
|
||||
Put ddlpa.h and ddlpa.c into the same directory and compile as test program by
|
||||
cc -g -Wall -DDDLPA_C_STANDALONE -o ddlpa ddlpa.c
|
||||
|
||||
Use it to occupy a drive's representations for a given number of seconds
|
||||
./ddlpa /dev/sr0 300
|
||||
|
||||
It should do no harm to any of your running activities.
|
||||
If it does: Please, please alert us.
|
||||
|
||||
Your own programs should not be able to circumvent the occupation if they
|
||||
obey above rules for Friendly Programs.
|
||||
Of course ./ddlpa should be unable to circumvent itself.
|
||||
|
||||
A successfull occupation looks like
|
||||
DDLPA_DEBUG: ddlpa_std_by_rdev("/dev/scd0") = "/dev/sr0"
|
||||
DDLPA_DEBUG: ddlpa_collect_siblings() found "/dev/sr0"
|
||||
DDLPA_DEBUG: ddlpa_collect_siblings() found "/dev/scd0"
|
||||
DDLPA_DEBUG: ddlpa_collect_siblings() found "/dev/sg0"
|
||||
DDLPA_DEBUG: ddlpa_occupy() : '/dev/scd0'
|
||||
DDLPA_DEBUG: ddlpa_occupy() O_EXCL : '/dev/sg0'
|
||||
DDLPA_DEBUG: ddlpa_occupy() O_EXCL : '/dev/sr0'
|
||||
---------------------------------------------- Lock gained
|
||||
ddlpa: opened /dev/sr0
|
||||
ddlpa: opened siblings: /dev/scd0 /dev/sg0
|
||||
slept 1 seconds of 300
|
||||
|
||||
Now an attempt via device file alias /dev/NEC must fail:
|
||||
DDLPA_DEBUG: ddlpa_std_by_rdev("/dev/NEC") = "/dev/sg0"
|
||||
DDLPA_DEBUG: ddlpa_collect_siblings() found "/dev/sr0"
|
||||
DDLPA_DEBUG: ddlpa_collect_siblings() found "/dev/scd0"
|
||||
DDLPA_DEBUG: ddlpa_collect_siblings() found "/dev/sg0"
|
||||
Cannot exclusively open '/dev/sg0'
|
||||
Reason given : Failed to open O_RDWR | O_NDELAY | O_EXCL : '/dev/sr0'
|
||||
Error condition : 16 'Device or resource busy'
|
||||
|
||||
With hdc, of course, things are trivial
|
||||
DDLPA_DEBUG: ddlpa_std_by_rdev("/dev/hdc") = "/dev/hdc"
|
||||
DDLPA_DEBUG: ddlpa_occupy() O_EXCL : '/dev/hdc'
|
||||
---------------------------------------------- Lock gained
|
||||
ddlpa: opened /dev/hdc
|
||||
slept 1 seconds of 1
|
||||
|
||||
|
||||
Ted Ts'o provided program open-cd-excl which allows to explore open(2) on
|
||||
device files with combinations of read-write, O_EXCL, and fcntl().
|
||||
(This does not mean that Ted endorsed our project yet. He helps exploring.)
|
||||
|
||||
Friendly in the sense of DDLP-A would be any run which uses at least one of
|
||||
the options -e (i.e. O_EXCL) or -f (i.e. F_SETLK, applied to a file
|
||||
descriptor which was obtained from a standard device file path).
|
||||
The code is available under GPL at
|
||||
http://libburnia.pykix.org/browser/libburn/trunk/test/open-cd-excl.c?format=txt
|
||||
To be compiled by
|
||||
cc -g -Wall -o open-cd-excl open-cd-excl.c
|
||||
|
||||
Options:
|
||||
-e : open O_EXCL
|
||||
-f : aquire lock by fcntl(F_SETLK) after sucessful open
|
||||
-i : do not wait in case of success but exit 0 immediately
|
||||
-r : open O_RDONLY , with -f use F_RDLCK
|
||||
-w : open O_RDWR , with -f use F_WRLCK
|
||||
plus the path of the devce file to open.
|
||||
|
||||
Friendly Programs would use gestures like:
|
||||
./open-cd-excl -e -r /dev/sr0
|
||||
./open-cd-excl -e -w /dev/sg1
|
||||
./open-cd-excl -e -w /dev/black-drive
|
||||
./open-cd-excl -f -r /dev/sg1
|
||||
./open-cd-excl -e -f -w /dev/sr0
|
||||
|
||||
Ignorant programs would use and cause potential trouble by:
|
||||
./open-cd-excl -r /dev/sr0
|
||||
./open-cd-excl -w /dev/sg1
|
||||
./open-cd-excl -f -w /dev/black-drive
|
||||
where "/dev/black-drive" is _not_ a symbolic link to
|
||||
any of /dev/sr* /dev/scd* /dev/sg* /dev/hd*, but has an own inode.
|
||||
|
||||
Prone to failure without further reason is:
|
||||
./open-cd-excl -e -r /dev/sg1
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
DDLP-B
|
||||
|
||||
This protocol relies on proxy lock files in some filesystem directory. It can
|
||||
be embedded into DDLP-A or it can be used be used standalone, outside DDLP-A.
|
||||
|
||||
DDLP-A shall be kept by DDLP-B from trying to access any device file which
|
||||
might already be in use. There is a problematic gesture in DDLP-A when SCSI
|
||||
address parameters are to be retrieved. For now this gesture seems to be
|
||||
harmless. But one never knows.
|
||||
Vice versa DDLP-B may get from DDLP-A the service to search for SCSI device
|
||||
file siblings. So they are best as a couple.
|
||||
|
||||
But they are not perfect. Not even as couple. fcntl() locking is flawed.
|
||||
|
||||
|
||||
There is a proxy file locking protocol described in FHS:
|
||||
http://www.pathname.com/fhs/pub/fhs-2.3.html#VARLOCKLOCKFILES
|
||||
|
||||
But it has shortcommings (see below). Decisive obstacle for its usage are the
|
||||
possibility for stale locks and the lack of shared locks.
|
||||
|
||||
DDLP-B rather defines a "path prefix" which is advised to be
|
||||
/tmp/ddlpb-lock-
|
||||
This prefix will get appended "device specific suffixes" and then form the path
|
||||
of a "lockfile".
|
||||
Not the existence of a lockfile but its occupation by an fcntl(F_SETLK) will
|
||||
constitute a lock. Lockfiles may get prepared by the sysadmin in directories
|
||||
where normal users are not allowed to create new files. Their rw-permissions
|
||||
then act as additional access restriction to the device files.
|
||||
The use of fcntl(F_SETLK) will prevent any stale locks after the process ended.
|
||||
It will also allow to obtain shared locks as well as exclusive locks.
|
||||
|
||||
There are two classes of device specific suffixes:
|
||||
|
||||
- Device file path suffix. Absolute paths only. "/" gets replaced by "_-".
|
||||
Eventual "_-" in path gets replaced by "_-_-". The leading group of "_-"
|
||||
is always interpreted as a group of "/", though. E.g.:
|
||||
/dev/sr0 <-> "_-dev_-sr0"
|
||||
/mydevs/burner/nec <-> "_-mydevs_-burners_-nec"
|
||||
/dev/rare_-name <-> "_-dev_-rare_-_-name"
|
||||
///strange/dev/x <-> "_-_-_-strange_-dev_-x"
|
||||
|
||||
- st_rdev suffix. A hex representation of struct stat.st_rdev. Capital letters.
|
||||
The number of characters is pare with at most one leading 0. I.e. bytewise
|
||||
printf("%2.2X") beginning with the highest order byte that is not zero.
|
||||
E.g. : "0B01", "2200", "01000000000004001"
|
||||
|
||||
If a lockfile does not exist and cannot be created then this shall not keep
|
||||
a program from working on a device. But if a lockfile exists and if permissions
|
||||
or locking state do not allow to obtain a lock of the appropirate type, then
|
||||
this shall prevent any opening of device file in question resp. shall cause
|
||||
immediate close(2) of an already opened device file.
|
||||
|
||||
The vulnerable programs shall not start their operation before they locked a
|
||||
wide collection of drive representations.
|
||||
|
||||
Non-vulnerable programs shall take care to lock the suffix resulting from the
|
||||
path they will be using and the suffix from the st_rdev from that path.
|
||||
The latter is to be obtained by call stat(2).
|
||||
|
||||
Locks get upheld as long as their file descriptor is not closed or no other
|
||||
incident as described in man 2 fcntl releases the lock.
|
||||
|
||||
So with shared locks there are no imandatory further activities after they
|
||||
have been obtained.
|
||||
|
||||
In case of exclusive locks, the file has to have been opened for writing and
|
||||
must be truncated to 0 bytes length immediately after obtaining the lock.
|
||||
When releasing an exclusive lock it is a nice gesture to
|
||||
already do this truncation.
|
||||
Then a /var/lock/ compatible first line has to be written.
|
||||
E.g. by: printf("%10u\n",(unsigned) getpid()) yielding " 1230\n".
|
||||
|
||||
Any further lines are optional. They shall have the form Name=Value and must
|
||||
be printable cleartext. If such further lines exist, then the last one must
|
||||
have the name "endmark".
|
||||
Defined Names are:
|
||||
hostid =hostname of the machine where the process number of line 1 is valid
|
||||
start =start time of lock in seconds since 1970. E.g: 1177147634.592410
|
||||
program =self chosen name of the program which obtained the lock
|
||||
argv0 =argv[0] of that program
|
||||
mainpath =device file path which will be used for operations by that program
|
||||
path =device file path which lead to the lock
|
||||
st_rdev =st_rdev suffix which is associated with path
|
||||
scsi_hcil=eventual SCSI parameters Host,Channel,Id,Lun
|
||||
scsi_bus =eventual SCSI parameter Bus
|
||||
endmark =declares the info as complete.
|
||||
Any undefined name or a line without "=" shall be handled as comment.
|
||||
"=" in the value is allowed. Any line beginning with an "=" character is an
|
||||
extension of the previous value.
|
||||
|
||||
If programs encounter an exclusive lock, they are invited to read the content
|
||||
of the lockfile anyway. But they should be aware that the info might be in the
|
||||
progress of emerging. There is a race condition possible in the short time
|
||||
between obtaining the exclusive lock and erasing the file content.
|
||||
If it is not crucial to obtain most accurate info then one may take the newline
|
||||
of the first line as indicator of a valid process number and the "endmark"
|
||||
name as indicator that the preceding lines are valid.
|
||||
Very cautious readers should obtain the info twice with a decent waiting period
|
||||
inbetween. Only if both results are identical they should be considered valid.
|
||||
|
||||
|
||||
There is no implementation of DDLP-B yet.
|
||||
|
||||
|
||||
|
||||
----------------------------------------------------------------------------
|
||||
What are the Stumble Stones ?
|
||||
----------------------------------------------------------------------------
|
||||
|
||||
Any of the considered locking mechanisms has decisive shortcommings
|
||||
which keeps it from being the solution to all known legitimate use cases.
|
||||
|
||||
The attempt has failed to compose a waterproof locking mechanism from means of
|
||||
POSIX, FHS and from hardly documented Linux open(O_EXCL) on device files.
|
||||
The resulting mechanisms would need about 1000 lines of code and still do
|
||||
not close all gaps resp. cover the well motivated use cases.
|
||||
This attempt you see above: DDLP-A and DDLP-B.
|
||||
|
||||
|
||||
Summary of the reasons why the established locking mechanisms do not suffice:
|
||||
|
||||
None of the mechanisms can take care of the double device driver identity
|
||||
sr versus sg. To deduce the one device file from the other involves the need
|
||||
to open many other (possibly unrelated) device files with the risk to disturb
|
||||
them.
|
||||
This hard to solve problem is aggravated by the following facts.
|
||||
|
||||
Shortcommings of Linux specific open(O_EXCL) :
|
||||
|
||||
- O_EXCL | O_RDONLY does not succeed with /dev/sg*
|
||||
- O_EXCL cannot provide shared locks for programs which only want to lock
|
||||
against burn programs but not against their own peers.
|
||||
- O_EXCL keeps from obtaining information by harmless activities.
|
||||
- O_EXCL already has a meaning with devices which are mounted as filesystems.
|
||||
This priority meaning is more liberal than the one needed for CD/DV recording
|
||||
protection.
|
||||
|
||||
Shortcommings of POSIX fcntl(F_SETLK) :
|
||||
|
||||
- fcntl() demands an open file descriptor. open(2) might have side effects.
|
||||
- fcntl() locks can be released inadvertedly by submodules which just open and
|
||||
close the same file (inode ?) without refering to fcntl locks in any way.
|
||||
See man 2 fcntl "This is bad:".
|
||||
Stacking of software modules is a widely used design pattern. But fcntl()
|
||||
cannot cope with that.
|
||||
|
||||
Shortcommings of FHS /var/lock/ :
|
||||
|
||||
- Stale locks are possible.
|
||||
- It is necessary to create a file (using the _old_ meaning of O_EXCL flag ?)
|
||||
but /var/lock/ might not be available early during system start and it often
|
||||
has restrictive permission settings.
|
||||
- There is no way to indicate a difference between exclusive and shared locks.
|
||||
- The FHS prescription relies entirely on the basename of the device file path.
|
||||
|
1182
doc/doxygen.conf.in
1182
doc/doxygen.conf.in
File diff suppressed because it is too large
Load Diff
1209
doc/mediainfo.txt
Normal file
1209
doc/mediainfo.txt
Normal file
File diff suppressed because it is too large
Load Diff
@ -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
|
||||
|
550
libburn/async.c
550
libburn/async.c
@ -1,15 +1,49 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
/* ts A71019 */
|
||||
|
||||
/* 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
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#include "libburn.h"
|
||||
#include "transport.h"
|
||||
#include "drive.h"
|
||||
#include "write.h"
|
||||
#include "options.h"
|
||||
#include "file.h"
|
||||
#include "async.h"
|
||||
#include "init.h"
|
||||
#include "back_hacks.h"
|
||||
|
||||
#include <pthread.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <signal.h>
|
||||
|
||||
/*
|
||||
#include <a ssert.h>
|
||||
@ -17,7 +51,15 @@
|
||||
#include "libdax_msgs.h"
|
||||
extern struct libdax_msgs *libdax_messenger;
|
||||
|
||||
#define SCAN_GOING() (workers && !workers->drive)
|
||||
/* ts A80714 : introduced type codes for the worker list */
|
||||
#define Burnworker_type_scaN 0
|
||||
#define Burnworker_type_erasE 1
|
||||
#define Burnworker_type_formaT 2
|
||||
#define Burnworker_type_writE 3
|
||||
#define Burnworker_type_fifO 4
|
||||
|
||||
#define SCAN_GOING() (workers != NULL && \
|
||||
workers->w_type == Burnworker_type_scaN)
|
||||
|
||||
typedef void *(*WorkerFunc) (void *);
|
||||
|
||||
@ -35,6 +77,14 @@ struct erase_opts
|
||||
int fast;
|
||||
};
|
||||
|
||||
/* ts A61230 */
|
||||
struct format_opts
|
||||
{
|
||||
struct burn_drive *drive;
|
||||
off_t size;
|
||||
int flag;
|
||||
};
|
||||
|
||||
struct write_opts
|
||||
{
|
||||
struct burn_drive *drive;
|
||||
@ -42,8 +92,18 @@ struct write_opts
|
||||
struct burn_disc *disc;
|
||||
};
|
||||
|
||||
struct fifo_opts
|
||||
{
|
||||
struct burn_source *source;
|
||||
int flag;
|
||||
};
|
||||
|
||||
|
||||
struct w_list
|
||||
{
|
||||
/* ts A80714 */
|
||||
int w_type; /* see above define Burnworker_type_* */
|
||||
|
||||
struct burn_drive *drive;
|
||||
pthread_t thread;
|
||||
|
||||
@ -53,11 +113,14 @@ struct w_list
|
||||
{
|
||||
struct scan_opts scan;
|
||||
struct erase_opts erase;
|
||||
struct format_opts format;
|
||||
struct write_opts write;
|
||||
struct fifo_opts fifo;
|
||||
} u;
|
||||
};
|
||||
|
||||
static struct w_list *workers;
|
||||
static struct w_list *workers = NULL;
|
||||
|
||||
|
||||
static struct w_list *find_worker(struct burn_drive *d)
|
||||
{
|
||||
@ -69,12 +132,19 @@ static struct w_list *find_worker(struct burn_drive *d)
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void add_worker(struct burn_drive *d, WorkerFunc f, void *data)
|
||||
static void add_worker(int w_type, struct burn_drive *d,
|
||||
WorkerFunc f, void *data)
|
||||
{
|
||||
struct w_list *a;
|
||||
struct w_list *tmp;
|
||||
pthread_attr_t *attr_pt = NULL;
|
||||
|
||||
a = malloc(sizeof(struct w_list));
|
||||
#ifdef Libburn_create_detached_threadS
|
||||
pthread_attr_t attr;
|
||||
#endif
|
||||
|
||||
a = calloc(1, sizeof(struct w_list));
|
||||
a->w_type = w_type;
|
||||
a->drive = d;
|
||||
a->u = *(union w_list_data *)data;
|
||||
|
||||
@ -83,26 +153,65 @@ static void add_worker(struct burn_drive *d, WorkerFunc f, void *data)
|
||||
tmp = workers;
|
||||
workers = a;
|
||||
|
||||
if (d)
|
||||
if (d != NULL)
|
||||
d->busy = BURN_DRIVE_SPAWNING;
|
||||
|
||||
if (pthread_create(&a->thread, NULL, f, a)) {
|
||||
#ifdef Libburn_create_detached_threadS
|
||||
/* ts A71019 :
|
||||
Trying to start the threads detached to get rid of the zombies
|
||||
which do neither react on pthread_join() nor on pthread_detach().
|
||||
*/
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
|
||||
attr_pt= &attr;
|
||||
/*
|
||||
libdax_msgs_submit(libdax_messenger, -1, 0x00020158,
|
||||
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_LOW,
|
||||
"add_worker(): Creating detached thread.", 0, 0);
|
||||
*/
|
||||
#endif
|
||||
|
||||
if (pthread_create(&a->thread, attr_pt, f, a)) {
|
||||
free(a);
|
||||
workers = tmp;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void remove_worker(pthread_t th)
|
||||
{
|
||||
struct w_list *a, *l = NULL;
|
||||
|
||||
#ifdef Libburn_detach_done_workeR
|
||||
int ret;
|
||||
char msg[80];
|
||||
#endif
|
||||
|
||||
for (a = workers; a; l = a, a = a->next)
|
||||
if (a->thread == th) {
|
||||
if (l)
|
||||
l->next = a->next;
|
||||
else
|
||||
workers = a->next;
|
||||
|
||||
#ifdef Libburn_detach_done_workeR
|
||||
/* ts A71019 : burry dead puppy before forgetting it */
|
||||
/* Alternative : threads get detached and thus should
|
||||
dispose themselves.
|
||||
*/
|
||||
ret = pthread_detach(th);
|
||||
/*
|
||||
sprintf(msg,
|
||||
"remove_workers(): pid= %lu pthread_detach(%lu)= %d",
|
||||
(unsigned long) getpid(), (unsigned long) th, ret);
|
||||
libdax_msgs_submit(libdax_messenger, -1, 0x00020158,
|
||||
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_LOW,
|
||||
msg, 0, 0);
|
||||
*/
|
||||
|
||||
#endif /* Libburn_detach_done_workeR */
|
||||
|
||||
free(a);
|
||||
break;
|
||||
}
|
||||
@ -117,11 +226,32 @@ static void remove_worker(pthread_t th)
|
||||
|
||||
static void *scan_worker_func(struct w_list *w)
|
||||
{
|
||||
burn_drive_scan_sync(w->u.scan.drives, w->u.scan.n_drives);
|
||||
w->u.scan.done = 1;
|
||||
int ret;
|
||||
|
||||
ret = burn_drive_scan_sync(w->u.scan.drives, w->u.scan.n_drives, 1);
|
||||
if (ret <= 0)
|
||||
w->u.scan.done = -1;
|
||||
else
|
||||
w->u.scan.done = 1;
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static void reset_progress(struct burn_drive *d, int sessions, int tracks,
|
||||
int indices, int sectors, int flag)
|
||||
{
|
||||
/* reset the progress indicator */
|
||||
d->progress.session = 0;
|
||||
d->progress.sessions = sessions;
|
||||
d->progress.track = 0;
|
||||
d->progress.tracks = tracks;
|
||||
d->progress.index = 0;
|
||||
d->progress.indices = indices;
|
||||
d->progress.start_sector = 0;
|
||||
d->progress.sectors = sectors;
|
||||
d->progress.sector = 0;
|
||||
}
|
||||
|
||||
|
||||
int burn_drive_scan(struct burn_drive_info *drives[], unsigned int *n_drives)
|
||||
{
|
||||
struct scan_opts o;
|
||||
@ -152,12 +282,13 @@ drive_is_active:;
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!workers) {
|
||||
if (workers == NULL) {
|
||||
/* start it */
|
||||
|
||||
/* ts A61007 : test moved up from burn_drive_scan_sync()
|
||||
was burn_wait_all() */
|
||||
if (!burn_drives_are_clear())
|
||||
/* ts A70907 : now demanding freed drives, not only released */
|
||||
if (!burn_drives_are_clear(1))
|
||||
goto drive_is_active;
|
||||
*drives = NULL;
|
||||
*n_drives = 0;
|
||||
@ -165,7 +296,8 @@ drive_is_active:;
|
||||
o.drives = drives;
|
||||
o.n_drives = n_drives;
|
||||
o.done = 0;
|
||||
add_worker(NULL, (WorkerFunc) scan_worker_func, &o);
|
||||
add_worker(Burnworker_type_scaN, NULL,
|
||||
(WorkerFunc) scan_worker_func, &o);
|
||||
} else if (workers->u.scan.done) {
|
||||
/* its done */
|
||||
ret = workers->u.scan.done;
|
||||
@ -176,7 +308,7 @@ drive_is_active:;
|
||||
if (workers != NULL) {
|
||||
libdax_msgs_submit(libdax_messenger, -1, 0x00020101,
|
||||
LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"After scan a drive operation is still going on",
|
||||
"After scan a drive operation is still going on",
|
||||
0, 0);
|
||||
return -1;
|
||||
}
|
||||
@ -189,8 +321,27 @@ drive_is_active:;
|
||||
|
||||
static void *erase_worker_func(struct w_list *w)
|
||||
{
|
||||
|
||||
#define Libburn_protect_erase_threaD 1
|
||||
|
||||
#ifdef Libburn_protect_erase_threaD
|
||||
sigset_t sigset, oldset;
|
||||
|
||||
/* Protect blank thread from being interrupted by external signals */
|
||||
sigfillset(&sigset);
|
||||
sigdelset(&sigset, SIGSEGV);
|
||||
sigdelset(&sigset, SIGILL);
|
||||
pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
|
||||
#endif /* Libburn_protect_erase_threaD */
|
||||
|
||||
burn_disc_erase_sync(w->u.erase.drive, w->u.erase.fast);
|
||||
remove_worker(pthread_self());
|
||||
|
||||
#ifdef Libburn_protect_erase_threaD
|
||||
/* (just in case it would not end with all signals blocked) */
|
||||
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
|
||||
#endif /* Libburn_protect_erase_threaD */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
@ -202,14 +353,15 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
|
||||
/* a ssert(drive); */
|
||||
/* a ssert(!SCAN_GOING()); */
|
||||
/* a ssert(!find_worker(drive)); */
|
||||
|
||||
if((drive == NULL)) {
|
||||
libdax_msgs_submit(libdax_messenger, drive->global_index,
|
||||
libdax_msgs_submit(libdax_messenger, -1,
|
||||
0x00020104,
|
||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"NULL pointer caught in burn_disc_erase", 0, 0);
|
||||
return;
|
||||
}
|
||||
if ((SCAN_GOING()) || find_worker(drive)) {
|
||||
if ((SCAN_GOING()) || find_worker(drive) != NULL) {
|
||||
libdax_msgs_submit(libdax_messenger, drive->global_index,
|
||||
0x00020102,
|
||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||
@ -218,59 +370,405 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
|
||||
return;
|
||||
}
|
||||
|
||||
reset_progress(drive, 1, 1, 1, 0x10000, 0);
|
||||
|
||||
/* 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() */
|
||||
/* ts B10321 : Allowed role 5 to be blanked */
|
||||
if ((drive->drive_role == 1 &&
|
||||
drive->current_profile != 0x0a &&
|
||||
drive->current_profile != 0x13 &&
|
||||
drive->current_profile != 0x14 &&
|
||||
drive->status != BURN_DISC_FULL)
|
||||
||
|
||||
(drive->status != BURN_DISC_FULL &&
|
||||
drive->status != BURN_DISC_APPENDABLE &&
|
||||
drive->status != BURN_DISC_BLANK)
|
||||
||
|
||||
(drive->drive_role != 1 && drive->drive_role != 5)
|
||||
) {
|
||||
libdax_msgs_submit(libdax_messenger, drive->global_index,
|
||||
0x00020130,
|
||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Drive and media state unsuitable for blanking",
|
||||
0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
o.drive = drive;
|
||||
o.fast = fast;
|
||||
add_worker(drive, (WorkerFunc) erase_worker_func, &o);
|
||||
add_worker(Burnworker_type_erasE, drive,
|
||||
(WorkerFunc) erase_worker_func, &o);
|
||||
}
|
||||
|
||||
|
||||
/* ts A61230 */
|
||||
static void *format_worker_func(struct w_list *w)
|
||||
{
|
||||
|
||||
#define Libburn_protect_format_threaD 1
|
||||
|
||||
#ifdef Libburn_protect_format_threaD
|
||||
sigset_t sigset, oldset;
|
||||
|
||||
/* Protect format thread from being interrupted by external signals */
|
||||
sigfillset(&sigset);
|
||||
sigdelset(&sigset, SIGSEGV);
|
||||
sigdelset(&sigset, SIGILL);
|
||||
pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
|
||||
#endif /* Libburn_protect_format_threaD */
|
||||
|
||||
burn_disc_format_sync(w->u.format.drive, w->u.format.size,
|
||||
w->u.format.flag);
|
||||
remove_worker(pthread_self());
|
||||
|
||||
#ifdef Libburn_protect_format_threaD
|
||||
/* (just in case it would not end with all signals blocked) */
|
||||
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
|
||||
#endif /* Libburn_protect_format_threaD */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
/* ts A61230 */
|
||||
void burn_disc_format(struct burn_drive *drive, off_t size, int flag)
|
||||
{
|
||||
struct format_opts o;
|
||||
int ok = 0, ret;
|
||||
char msg[40];
|
||||
|
||||
reset_progress(drive, 1, 1, 1, 0x10000, 0);
|
||||
|
||||
if ((SCAN_GOING()) || find_worker(drive) != NULL) {
|
||||
libdax_msgs_submit(libdax_messenger, drive->global_index,
|
||||
0x00020102,
|
||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"A drive operation is still going on (want to format)",
|
||||
0, 0);
|
||||
return;
|
||||
}
|
||||
if (drive->drive_role != 1) {
|
||||
libdax_msgs_submit(libdax_messenger, drive->global_index,
|
||||
0x00020146,
|
||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Drive is a virtual placeholder", 0, 0);
|
||||
drive->cancel = 1;
|
||||
return;
|
||||
}
|
||||
if (flag & 128) /* application prescribed format type */
|
||||
flag |= 16; /* enforce re-format */
|
||||
|
||||
if (drive->current_profile == 0x14)
|
||||
ok = 1; /* DVD-RW sequential */
|
||||
else if (drive->current_profile == 0x13 && (flag & 16))
|
||||
ok = 1; /* DVD-RW Restricted Overwrite with force bit */
|
||||
else if (drive->current_profile == 0x1a) {
|
||||
ok = 1; /* DVD+RW */
|
||||
size = 0;
|
||||
flag &= ~(2|8); /* no insisting in size 0, no expansion */
|
||||
flag |= 4; /* format up to maximum size */
|
||||
} else if (drive->current_profile == 0x12) {
|
||||
ok = 1; /* DVD-RAM */
|
||||
|
||||
} else if (drive->current_profile == 0x41) {
|
||||
/* BD-R SRM */
|
||||
ok= 1;
|
||||
ret = drive->read_format_capacities(drive, 0x00);
|
||||
if (ret > 0 &&
|
||||
drive->format_descr_type == BURN_FORMAT_IS_FORMATTED)
|
||||
ok = 0;
|
||||
if (drive->status != BURN_DISC_BLANK)
|
||||
ok = 0;
|
||||
if (!ok) {
|
||||
libdax_msgs_submit(libdax_messenger,
|
||||
drive->global_index, 0x00020162,
|
||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"BD-R not unformatted blank any more. Cannot format.",
|
||||
0, 0);
|
||||
drive->cancel = 1;
|
||||
return;
|
||||
}
|
||||
if (flag & 32) {
|
||||
libdax_msgs_submit(libdax_messenger,
|
||||
drive->global_index, 0x00020163,
|
||||
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Blank BD-R left unformatted for zero spare capacity.",
|
||||
0, 0);
|
||||
return;
|
||||
}
|
||||
} else if (drive->current_profile == 0x43) {
|
||||
ok = 1; /* BD-RE */
|
||||
|
||||
if ((flag & 32) && !(drive->current_feat23h_byte4 & 8)) {
|
||||
libdax_msgs_submit(libdax_messenger,
|
||||
drive->global_index, 0x00020164,
|
||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Drive does not format BD-RE without spares.",
|
||||
0, 0);
|
||||
drive->cancel = 1;
|
||||
return;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
if (!ok) {
|
||||
sprintf(msg,"Will not format media type %4.4Xh",
|
||||
drive->current_profile);
|
||||
libdax_msgs_submit(libdax_messenger, drive->global_index,
|
||||
0x00020129,
|
||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||
msg, 0, 0);
|
||||
drive->cancel = 1;
|
||||
return;
|
||||
}
|
||||
o.drive = drive;
|
||||
o.size = size;
|
||||
o.flag = flag;
|
||||
add_worker(Burnworker_type_formaT, drive,
|
||||
(WorkerFunc) format_worker_func, &o);
|
||||
}
|
||||
|
||||
|
||||
static void *write_disc_worker_func(struct w_list *w)
|
||||
{
|
||||
struct burn_drive *d = w->u.write.drive;
|
||||
char msg[80];
|
||||
|
||||
#define Libburn_protect_write_threaD 1
|
||||
|
||||
#ifdef Libburn_protect_write_threaD
|
||||
sigset_t sigset, oldset;
|
||||
|
||||
/* Protect write thread from being interrupted by external signals */
|
||||
sigfillset(&sigset);
|
||||
sigdelset(&sigset, SIGSEGV);
|
||||
sigdelset(&sigset, SIGILL);
|
||||
pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
|
||||
#endif /* Libburn_protect_write_threaD */
|
||||
|
||||
d->thread_pid = getpid();
|
||||
d->thread_tid = pthread_self();
|
||||
d->thread_pid_valid= 1;
|
||||
burn_disc_write_sync(w->u.write.opts, w->u.write.disc);
|
||||
d->thread_pid_valid= 0;
|
||||
d->thread_pid = 0;
|
||||
|
||||
/* the options are refcounted, free out ref count which we added below
|
||||
*/
|
||||
burn_write_opts_free(w->u.write.opts);
|
||||
|
||||
sprintf(msg, "Write thread on drive %d ended", d->global_index);
|
||||
libdax_msgs_submit(libdax_messenger, d->global_index, 0x00020178,
|
||||
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
|
||||
msg, 0, 0);
|
||||
|
||||
remove_worker(pthread_self());
|
||||
d->busy = BURN_DRIVE_IDLE;
|
||||
|
||||
#ifdef Libburn_protect_write_threaD
|
||||
/* (just in case it would not end with all signals blocked) */
|
||||
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
|
||||
#endif /* Libburn_protect_write_threaD */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
|
||||
{
|
||||
int ret;
|
||||
struct write_opts o;
|
||||
char *reasons= NULL;
|
||||
struct burn_drive *d;
|
||||
|
||||
d = opts->drive;
|
||||
|
||||
/* ts A61006 */
|
||||
/* a ssert(!SCAN_GOING()); */
|
||||
/* a ssert(!find_worker(opts->drive)); */
|
||||
if ((SCAN_GOING()) || find_worker(opts->drive)) {
|
||||
libdax_msgs_submit(libdax_messenger, opts->drive->global_index,
|
||||
if ((SCAN_GOING()) || find_worker(opts->drive) != NULL) {
|
||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||
0x00020102,
|
||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"A drive operation is still going on (want to write)",
|
||||
0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
reset_progress(d, disc->sessions, disc->session[0]->tracks,
|
||||
disc->session[0]->track[0]->indices, 0, 0);
|
||||
|
||||
/* For the next lines any return indicates failure */
|
||||
d->cancel = 1;
|
||||
|
||||
/* ts A70203 : people have been warned in API specs */
|
||||
if (opts->write_type == BURN_WRITE_NONE) {
|
||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||
0x0002017c,
|
||||
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"No valid write type selected", 0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
if (d->drive_role == 4) {
|
||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||
0x00020181,
|
||||
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Pseudo-drive is a read-only file. Cannot write.",
|
||||
0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
/* ts A61007 : obsolete Assert in spc_select_write_params() */
|
||||
if (!opts->drive->mdata->valid) {
|
||||
if (d->drive_role == 1 && d->mdata->valid <= 0) {
|
||||
libdax_msgs_submit(libdax_messenger,
|
||||
opts->drive->global_index, 0x00020113,
|
||||
d->global_index, 0x00020113,
|
||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Drive capabilities not inquired yet", 0, 0);
|
||||
return;
|
||||
}
|
||||
/* ts A61009 : obsolete Assert in sector_headers() */
|
||||
if (! burn_disc_write_is_ok(opts, disc)) /* issues own msgs */
|
||||
return;
|
||||
|
||||
o.drive = opts->drive;
|
||||
/* ts A70219 : intended to replace all further tests here and many
|
||||
tests in burn_*_write_sync()
|
||||
*/
|
||||
|
||||
BURN_ALLOC_MEM(reasons, char, BURN_REASONS_LEN + 80);
|
||||
strcpy(reasons, "Write job parameters are unsuitable:\n");
|
||||
if (burn_precheck_write(opts, disc, reasons + strlen(reasons), 1)
|
||||
<= 0) {
|
||||
libdax_msgs_submit(libdax_messenger,
|
||||
d->global_index, 0x00020139,
|
||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||
reasons, 0, 0);
|
||||
goto ex;
|
||||
}
|
||||
BURN_FREE_MEM(reasons); reasons= NULL;
|
||||
|
||||
/* ts A90106 : early catching of unformatted BD-RE */
|
||||
if (d->current_profile == 0x43)
|
||||
if (d->read_format_capacities(d, 0x00) > 0 &&
|
||||
d->format_descr_type != BURN_FORMAT_IS_FORMATTED) {
|
||||
libdax_msgs_submit(libdax_messenger,
|
||||
d->global_index, 0x00020168,
|
||||
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Media not properly formatted. Cannot write.",
|
||||
0, 0);
|
||||
return;
|
||||
}
|
||||
|
||||
d->cancel = 0; /* End of the return = failure area */
|
||||
|
||||
o.drive = d;
|
||||
o.opts = opts;
|
||||
o.disc = disc;
|
||||
|
||||
opts->refcount++;
|
||||
|
||||
add_worker(opts->drive, (WorkerFunc) write_disc_worker_func, &o);
|
||||
add_worker(Burnworker_type_writE, d,
|
||||
(WorkerFunc) write_disc_worker_func, &o);
|
||||
|
||||
ex:;
|
||||
BURN_FREE_MEM(reasons);
|
||||
}
|
||||
|
||||
|
||||
static void *fifo_worker_func(struct w_list *w)
|
||||
{
|
||||
int old;
|
||||
|
||||
#define Libburn_protect_fifo_threaD 1
|
||||
|
||||
#ifdef Libburn_protect_fifo_threaD
|
||||
sigset_t sigset, oldset;
|
||||
|
||||
/* Protect fifo thread from being interrupted by external signals */
|
||||
sigfillset(&sigset);
|
||||
sigdelset(&sigset, SIGSEGV);
|
||||
sigdelset(&sigset, SIGILL);
|
||||
pthread_sigmask(SIG_SETMASK, &sigset, &oldset);
|
||||
#endif /* Libburn_protect_fifo_threaD */
|
||||
|
||||
pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, &old);
|
||||
pthread_setcanceltype(PTHREAD_CANCEL_ASYNCHRONOUS, &old);
|
||||
/* Note: Only burn_fifo_abort() shall cancel the fifo thread */
|
||||
|
||||
burn_fifo_source_shoveller(w->u.fifo.source, w->u.fifo.flag);
|
||||
remove_worker(pthread_self());
|
||||
|
||||
#ifdef Libburn_protect_fifo_threaD
|
||||
/* (just in case it would not end with all signals blocked) */
|
||||
pthread_sigmask(SIG_SETMASK, &oldset, NULL);
|
||||
#endif /* Libburn_protect_fifo_threaD */
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
||||
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 = burn_os_alloc_buffer(
|
||||
((size_t) fs->chunksize) * (size_t) fs->chunks, 0);
|
||||
if (fs->buf == NULL) {
|
||||
/* >>> could not start ring buffer */;
|
||||
return -1;
|
||||
}
|
||||
|
||||
o.source = source;
|
||||
o.flag = flag;
|
||||
add_worker(Burnworker_type_fifO, NULL,
|
||||
(WorkerFunc) fifo_worker_func, &o);
|
||||
fs->is_started = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
int burn_fifo_abort(struct burn_source_fifo *fs, int flag)
|
||||
{
|
||||
int ret;
|
||||
pthread_t pt;
|
||||
|
||||
if (fs->thread_is_valid <= 0 || fs->thread_handle == NULL)
|
||||
return(2);
|
||||
|
||||
#ifdef NIX
|
||||
libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
|
||||
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Aborting running burn_source_fifo thread", 0, 0);
|
||||
#endif /* NIX */
|
||||
|
||||
pt= *((pthread_t *) fs->thread_handle);
|
||||
remove_worker(pt);
|
||||
ret = pthread_cancel(pt);
|
||||
return (ret == 0);
|
||||
}
|
||||
|
||||
|
||||
#ifdef Libburn_has_burn_async_join_alL
|
||||
|
||||
/* ts A71019 : never used */
|
||||
void burn_async_join_all(void)
|
||||
{
|
||||
void *ret;
|
||||
@ -278,3 +776,7 @@ void burn_async_join_all(void)
|
||||
while (workers)
|
||||
pthread_join(workers->thread, &ret);
|
||||
}
|
||||
|
||||
#endif /* Libburn_has_burn_async_join_alL */
|
||||
|
||||
|
||||
|
@ -5,4 +5,14 @@
|
||||
|
||||
void burn_async_join_all(void);
|
||||
struct burn_write_opts;
|
||||
|
||||
/* ts A70930 */
|
||||
/* To be called when the first read() call comes to a fifo */
|
||||
int burn_fifo_start(struct burn_source *source, int flag);
|
||||
|
||||
/* ts A81108 */
|
||||
/* To abort a running fifo thread before the fifo object gets deleted */
|
||||
int burn_fifo_abort(struct burn_source_fifo *fs, int flag);
|
||||
|
||||
|
||||
#endif /* BURN__ASYNC_H */
|
||||
|
@ -1,4 +1,6 @@
|
||||
/**
|
||||
Copyright (c) 2006 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
|
||||
This file bundles variables which disable changes in libburn which are
|
||||
not yet completely accepted.
|
||||
|
@ -3,13 +3,17 @@
|
||||
|
||||
A signal handler which cleans up an application and exits.
|
||||
|
||||
Provided under GPL license within GPL projects, BSD license elsewise.
|
||||
Provided under GPLv2+ license within GPL projects, BSD license elsewise.
|
||||
*/
|
||||
|
||||
/*
|
||||
cc -g -o cleanup -DCleanup_standalonE cleanup.c
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@ -23,31 +27,28 @@ typedef void (*sighandler_t)(int);
|
||||
|
||||
#include "cleanup.h"
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#ifndef Cleanup_has_no_libburn_os_H
|
||||
|
||||
|
||||
#include "../libburn/os.h"
|
||||
|
||||
/* see os.h for name of particular os-*.h where this is defined */
|
||||
static int signal_list[]= { BURN_OS_SIGNAL_MACRO_LIST , -1};
|
||||
static char *signal_name_list[]= { BURN_OS_SIGNAL_NAME_LIST , "@"};
|
||||
static int signal_list_count= BURN_OS_SIGNAL_COUNT;
|
||||
static int non_signal_list[]= { BURN_OS_NON_SIGNAL_MACRO_LIST, -1};
|
||||
static int non_signal_list_count= BURN_OS_NON_SIGNAL_COUNT;
|
||||
|
||||
|
||||
#else /* ! Cleanup_has_no_libburn_os_H */
|
||||
|
||||
|
||||
/* Outdated. GNU/Linux only.
|
||||
For backward compatibility with pre-libburn-0.2.3 */
|
||||
|
||||
/* Signals to be caught */
|
||||
static int signal_list[]= {
|
||||
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT,
|
||||
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM,
|
||||
SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN,
|
||||
SIGTTOU,
|
||||
SIGBUS, SIGPROF, SIGSYS, SIGTRAP,
|
||||
SIGVTALRM, SIGXCPU, SIGXFSZ, -1
|
||||
};
|
||||
static char *signal_name_list[]= {
|
||||
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT",
|
||||
"SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM",
|
||||
"SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN",
|
||||
"SIGTTOU",
|
||||
"SIGBUS", "SIGPROF", "SIGSYS", "SIGTRAP",
|
||||
"SIGVTALRM", "SIGXCPU", "SIGXFSZ", "@"
|
||||
};
|
||||
static int signal_list_count= 23;
|
||||
|
||||
#else /* __FreeBSD__ */
|
||||
|
||||
/* Signals to be caught */
|
||||
static int signal_list[]= {
|
||||
static int signal_list[]= {
|
||||
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT,
|
||||
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM,
|
||||
SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN,
|
||||
@ -55,7 +56,7 @@ static int signal_list[]= {
|
||||
SIGBUS, SIGPOLL, SIGPROF, SIGSYS, SIGTRAP,
|
||||
SIGVTALRM, SIGXCPU, SIGXFSZ, -1
|
||||
};
|
||||
static char *signal_name_list[]= {
|
||||
static char *signal_name_list[]= {
|
||||
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT",
|
||||
"SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM",
|
||||
"SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN",
|
||||
@ -65,18 +66,21 @@ static char *signal_name_list[]= {
|
||||
};
|
||||
static int signal_list_count= 24;
|
||||
|
||||
#endif /* ! __FreeBSD__ */
|
||||
|
||||
/* Signals not to be caught */
|
||||
static int non_signal_list[]= {
|
||||
SIGKILL, SIGCHLD, SIGSTOP, SIGURG, -1
|
||||
};
|
||||
static int non_signal_list_count= 4;
|
||||
SIGKILL, SIGCHLD, SIGSTOP, SIGURG, SIGWINCH, -1
|
||||
};
|
||||
static int non_signal_list_count= 5;
|
||||
|
||||
|
||||
#endif /* Cleanup_has_no_libburn_os_H */
|
||||
|
||||
|
||||
|
||||
/* run time dynamic part */
|
||||
static char cleanup_msg[4096]= {""};
|
||||
static int cleanup_exiting= 0;
|
||||
static int cleanup_has_reported= -1234567890;
|
||||
|
||||
static void *cleanup_app_handle= NULL;
|
||||
static Cleanup_app_handler_T cleanup_app_handler= NULL;
|
||||
@ -87,8 +91,10 @@ static int Cleanup_handler_exit(int exit_value, int signum, int flag)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if(cleanup_msg[0]!=0)
|
||||
if(cleanup_msg[0]!=0 && cleanup_has_reported!=signum) {
|
||||
fprintf(stderr,"\n%s\n",cleanup_msg);
|
||||
cleanup_has_reported= signum;
|
||||
}
|
||||
if(cleanup_perform_app_handler_first)
|
||||
if(cleanup_app_handler!=NULL) {
|
||||
ret= (*cleanup_app_handler)(cleanup_app_handle,signum,0);
|
||||
@ -96,8 +102,8 @@ static int Cleanup_handler_exit(int exit_value, int signum, int flag)
|
||||
return(2);
|
||||
}
|
||||
if(cleanup_exiting) {
|
||||
fprintf(stderr,"cleanup: ABORT : repeat by pid=%d, signum=%d\n",
|
||||
getpid(),signum);
|
||||
fprintf(stderr,"cleanup: ABORT : repeat by pid=%.f, signum=%d\n",
|
||||
(double) getpid(), signum);
|
||||
return(0);
|
||||
}
|
||||
cleanup_exiting= 1;
|
||||
|
@ -3,7 +3,7 @@
|
||||
|
||||
A signal handler which cleans up an application and exits.
|
||||
|
||||
Provided under GPL license within GPL projects, BSD license elsewise.
|
||||
Provided under GPLv2+ within GPL projects, BSD license elsewise.
|
||||
*/
|
||||
|
||||
#ifndef Cleanup_includeD
|
||||
|
@ -1,5 +1,9 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#include "crc.h"
|
||||
|
||||
static unsigned short ccitt_table[256] = {
|
||||
@ -104,6 +108,15 @@ unsigned long crc32_table[256] = {
|
||||
0x71C0FC00L, 0xE151FD01L, 0xE0E1FE01L, 0x7070FF00L
|
||||
};
|
||||
|
||||
|
||||
/* Exploration ts B00214 :
|
||||
ECMA-130, 22.3.6 "CRC field"
|
||||
Generating polynomial: x^16 + x^12 + x^5 + 1
|
||||
Also known as CRC-16-CCITT, CRC-CCITT
|
||||
|
||||
Use in libburn for raw write modes in sector.c.
|
||||
There is also disabled code in read.c which would use it.
|
||||
*/
|
||||
unsigned short crc_ccitt(unsigned char *q, int len)
|
||||
{
|
||||
unsigned short crc = 0;
|
||||
@ -112,6 +125,20 @@ unsigned short crc_ccitt(unsigned char *q, int len)
|
||||
crc = ccitt_table[(crc >> 8 ^ *q++) & 0xff] ^ (crc << 8);
|
||||
return ~crc;
|
||||
}
|
||||
|
||||
|
||||
/* Exploration ts B00214 :
|
||||
ECMA-130, 14.3 "EDC field"
|
||||
"The EDC codeword must be divisible by the check polynomial:
|
||||
P(x) = (x^16 + x^15 + x^2 + 1) . (x^16 + x^2 + x + 1)
|
||||
"
|
||||
|
||||
>>> Test whether this coincides with CRC-32 IEEE 802.3
|
||||
x^32 + x^26 + x^23 + x^22 + x^16 + x^12 + x^11 + x^10
|
||||
+ x^8 + x^7 + x^5 + x^4 + x^2 + x + 1
|
||||
|
||||
Used for raw writing in sector.c
|
||||
*/
|
||||
unsigned int crc_32(unsigned char *data, int len)
|
||||
{
|
||||
unsigned int crc = 0;
|
||||
|
@ -3,7 +3,21 @@
|
||||
#ifndef BURN__CRC_H
|
||||
#define BURN__CRC_H
|
||||
|
||||
|
||||
#ifdef Xorriso_standalonE
|
||||
/* Source module crc.c of yet unclear ancestry is excluded from GNU xorriso */
|
||||
#ifndef Libburn_no_crc_C
|
||||
#define Libburn_no_crc_C 1
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#ifndef Libburn_no_crc_C
|
||||
|
||||
unsigned short crc_ccitt(unsigned char *, int len);
|
||||
unsigned int crc_32(unsigned char *, int len);
|
||||
|
||||
#endif /* Libburn_no_crc_C */
|
||||
|
||||
|
||||
#endif /* BURN__CRC_H */
|
||||
|
618
libburn/ddlpa.c
Normal file
618
libburn/ddlpa.c
Normal file
@ -0,0 +1,618 @@
|
||||
|
||||
/* ddlpa
|
||||
Implementation of Delicate Device Locking Protocol level A.
|
||||
Copyright (C) 2007 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under any of the following licenses: GPL, LGPL, BSD. Choose one.
|
||||
|
||||
|
||||
Compile as test program:
|
||||
|
||||
cc -g -Wall \
|
||||
-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1 -D_LARGEFILE64_SOURCE \
|
||||
-DDDLPA_C_STANDALONE -o ddlpa ddlpa.c
|
||||
|
||||
The system macros enable 64-bit off_t and open(2) flag O_LARGEFILE, which
|
||||
are not absolutely necessary but explicitely take into respect that
|
||||
our devices can offer more than 2 GB of addressable data.
|
||||
|
||||
Run test program:
|
||||
|
||||
./ddlpa /dev/sr0 15
|
||||
./ddlpa 0,0,0 15
|
||||
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <scsi/scsi.h>
|
||||
|
||||
|
||||
/* All callers of ddlpa must do this */
|
||||
#include "ddlpa.h"
|
||||
|
||||
|
||||
/* 1 = Enable progress message on stderr, 0 = normal silent operation */
|
||||
static int ddlpa_debug_mode = 1;
|
||||
|
||||
|
||||
/* #define _GNU_SOURCE or _LARGEFILE64_SOURCE to get real O_LARGEFILE */
|
||||
#ifndef O_LARGEFILE
|
||||
#define O_LARGEFILE 0
|
||||
#endif
|
||||
|
||||
|
||||
/* ----------------------- private -------------------- */
|
||||
|
||||
|
||||
static int ddlpa_new(struct ddlpa_lock **lck, int o_flags, int ddlpa_flags)
|
||||
{
|
||||
int i;
|
||||
struct ddlpa_lock *o;
|
||||
|
||||
o = *lck = (struct ddlpa_lock *) malloc(sizeof(struct ddlpa_lock));
|
||||
if (o == NULL)
|
||||
return ENOMEM;
|
||||
for (i = 0; i < sizeof(struct ddlpa_lock); i++)
|
||||
((char *) o)[i] = 0;
|
||||
o->path = NULL;
|
||||
o->fd = -1;
|
||||
for (i = 0; i < DDLPA_MAX_SIBLINGS; i++)
|
||||
o->sibling_fds[i] = -1;
|
||||
o->errmsg = NULL;
|
||||
|
||||
o->o_flags = o_flags;
|
||||
o->ddlpa_flags = ddlpa_flags;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ddlpa_enumerate(struct ddlpa_lock *o, int *idx,
|
||||
char path[DDLPA_MAX_STD_LEN + 1])
|
||||
{
|
||||
if (*idx < 0)
|
||||
*idx = 0;
|
||||
|
||||
if (*idx < 26)
|
||||
sprintf(path, "/dev/hd%c", 'a' + *idx);
|
||||
else if (*idx < 256 + 26)
|
||||
sprintf(path, "/dev/sr%d", *idx - 26);
|
||||
else if (*idx < 2 * 256 + 26)
|
||||
sprintf(path, "/dev/scd%d", *idx - 256 - 26);
|
||||
else if (*idx < 3 * 256 + 26)
|
||||
sprintf(path, "/dev/sg%d", *idx - 2 * 256 - 26);
|
||||
else
|
||||
return 1;
|
||||
(*idx)++;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ddlpa_std_by_rdev(struct ddlpa_lock *o)
|
||||
{
|
||||
int idx = 0;
|
||||
char try_path[DDLPA_MAX_STD_LEN+1];
|
||||
struct stat path_stbuf, try_stbuf;
|
||||
|
||||
if (!o->path_is_valid)
|
||||
return EFAULT;
|
||||
if (stat(o->path, &path_stbuf) == -1)
|
||||
return errno;
|
||||
|
||||
while (ddlpa_enumerate(o, &idx, try_path) == 0) {
|
||||
if (stat(try_path, &try_stbuf) == -1)
|
||||
continue;
|
||||
if (path_stbuf.st_rdev != try_stbuf.st_rdev)
|
||||
continue;
|
||||
strcpy(o->std_path, try_path);
|
||||
|
||||
if (ddlpa_debug_mode)
|
||||
fprintf(stderr,
|
||||
"DDLPA_DEBUG: ddlpa_std_by_rdev(\"%s\") = \"%s\"\n",
|
||||
o->path, o->std_path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
|
||||
/* Caution : these tests are valid only with standard paths */
|
||||
|
||||
static int ddlpa_is_scsi(struct ddlpa_lock *o, char *path)
|
||||
{
|
||||
return (strncmp(path, "/dev/s", 6) == 0);
|
||||
}
|
||||
|
||||
static int ddlpa_is_sg(struct ddlpa_lock *o, char *path)
|
||||
{
|
||||
return (strncmp(path, "/dev/sg", 7) == 0);
|
||||
}
|
||||
|
||||
static int ddlpa_is_sr(struct ddlpa_lock *o, char *path)
|
||||
{
|
||||
return (strncmp(path, "/dev/sr", 7) == 0);
|
||||
}
|
||||
|
||||
static int ddlpa_is_scd(struct ddlpa_lock *o, char *path)
|
||||
{
|
||||
return (strncmp(path, "/dev/scd", 8) == 0);
|
||||
}
|
||||
|
||||
|
||||
static int ddlpa_fcntl_lock(struct ddlpa_lock *o, int fd, int l_type)
|
||||
{
|
||||
struct flock lockthing;
|
||||
int ret;
|
||||
|
||||
memset(&lockthing, 0, sizeof(lockthing));
|
||||
lockthing.l_type = l_type;
|
||||
lockthing.l_whence = SEEK_SET;
|
||||
lockthing.l_start = 0;
|
||||
lockthing.l_len = 0;
|
||||
ret = fcntl(fd, F_SETLK, &lockthing);
|
||||
if (ret == -1)
|
||||
return EBUSY;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ddlpa_occupy(struct ddlpa_lock *o, char *path, int *fd,
|
||||
int no_o_excl)
|
||||
{
|
||||
int ret, o_flags, o_rw, l_type;
|
||||
char *o_rwtext;
|
||||
|
||||
o_flags = o->o_flags | O_NDELAY;
|
||||
if(!no_o_excl)
|
||||
o_flags |= O_EXCL;
|
||||
o_rw = (o_flags) & (O_RDONLY | O_WRONLY | O_RDWR);
|
||||
o_rwtext = (o_rw == O_RDONLY ? "O_RDONLY" :
|
||||
(o_rw == O_WRONLY ? "O_WRONLY" :
|
||||
(o_rw == O_RDWR ? "O_RDWR " : "O_?rw-mode?")));
|
||||
|
||||
*fd = open(path, o_flags);
|
||||
if (*fd == -1) {
|
||||
o->errmsg = malloc(strlen(path)+160);
|
||||
if (o->errmsg)
|
||||
sprintf(o->errmsg,
|
||||
"Failed to open %s | O_NDELAY %s: '%s'",
|
||||
o_rwtext,
|
||||
(o_flags & O_EXCL ? "| O_EXCL " : ""), path);
|
||||
return (errno ? errno : EBUSY);
|
||||
}
|
||||
if (o_rw == O_RDWR || o_rw == O_WRONLY)
|
||||
l_type = F_WRLCK;
|
||||
else
|
||||
l_type = F_RDLCK;
|
||||
ret = ddlpa_fcntl_lock(o, *fd, l_type);
|
||||
if (ret) {
|
||||
o->errmsg = malloc(strlen(path)+160);
|
||||
if (o->errmsg)
|
||||
sprintf(o->errmsg,
|
||||
"Failed to lock fcntl(F_WRLCK) : '%s'",path);
|
||||
close(*fd);
|
||||
*fd = -1;
|
||||
return ret;
|
||||
}
|
||||
if (ddlpa_debug_mode)
|
||||
fprintf(stderr, "DDLPA_DEBUG: ddlpa_occupy() %s %s: '%s'\n",
|
||||
o_rwtext,
|
||||
(no_o_excl ? " " : "O_EXCL "), path);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ddlpa_obtain_scsi_adr(struct ddlpa_lock *o, char *path,
|
||||
int *bus, int *host, int *channel, int *id, int *lun)
|
||||
{
|
||||
int fd, ret, open_mode = O_RDONLY | O_NDELAY;
|
||||
struct my_scsi_idlun {
|
||||
int x;
|
||||
int host_unique_id;
|
||||
};
|
||||
struct my_scsi_idlun idlun;
|
||||
|
||||
fd = open(path, open_mode);
|
||||
if (fd == -1)
|
||||
return (errno ? errno : EBUSY);
|
||||
if (ioctl(fd, SCSI_IOCTL_GET_BUS_NUMBER, bus) == -1)
|
||||
*bus = -1;
|
||||
ret = ioctl(fd, SCSI_IOCTL_GET_IDLUN, &idlun);
|
||||
close(fd);
|
||||
if (ret == -1)
|
||||
return (errno ? errno : EIO);
|
||||
*host = (idlun.x >> 24) & 255;
|
||||
*channel = (idlun.x >> 16) & 255;
|
||||
*id = (idlun.x) & 255;
|
||||
*lun = (idlun.x >> 8 ) & 255;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int ddlpa_collect_siblings(struct ddlpa_lock *o)
|
||||
{
|
||||
int idx = 0, ret, have_sg = 0, have_sr = 0, have_scd = 0;
|
||||
dev_t path_dev;
|
||||
ino_t path_inode;
|
||||
struct stat stbuf;
|
||||
char *path, try_path[DDLPA_MAX_STD_LEN+1];
|
||||
int t_bus, t_host, t_channel, t_id, t_lun;
|
||||
|
||||
if (o->ddlpa_flags & DDLPA_OPEN_GIVEN_PATH)
|
||||
path = o->path;
|
||||
else
|
||||
path = o->std_path;
|
||||
if (path[0] == 0 || o->num_siblings != 0)
|
||||
return EFAULT;
|
||||
if (!ddlpa_is_scsi(o, o->std_path))
|
||||
return EFAULT;
|
||||
|
||||
if (stat(path, &stbuf) == -1)
|
||||
return errno;
|
||||
path_inode = stbuf.st_ino;
|
||||
path_dev = stbuf.st_dev;
|
||||
o->rdev = stbuf.st_rdev;
|
||||
o->dev = stbuf.st_dev;
|
||||
o->ino = stbuf.st_ino;
|
||||
ret = ddlpa_obtain_scsi_adr(o, path,
|
||||
&(o->bus), &(o->host), &(o->channel),
|
||||
&(o->id), &(o->lun));
|
||||
if (ret) {
|
||||
o->errmsg = strdup(
|
||||
"Cannot obtain SCSI parameters host,channel,id,lun");
|
||||
return ret;
|
||||
}
|
||||
o->hcilb_is_valid = 1;
|
||||
|
||||
while (ddlpa_enumerate(o, &idx, try_path) == 0) {
|
||||
if (!ddlpa_is_scsi(o, try_path))
|
||||
continue;
|
||||
if (stat(try_path, &stbuf) == -1)
|
||||
continue;
|
||||
ret = ddlpa_obtain_scsi_adr(o, try_path,
|
||||
&t_bus, &t_host, &t_channel, &t_id, &t_lun);
|
||||
if (ret) {
|
||||
|
||||
/* >>> interpret error, memorize busy, no permission */
|
||||
|
||||
continue;
|
||||
}
|
||||
if (t_host != o->host || t_channel != o->channel ||
|
||||
t_id != o->id || t_lun != o->lun)
|
||||
continue;
|
||||
|
||||
if (o->num_siblings >= DDLPA_MAX_SIBLINGS) {
|
||||
o->errmsg =
|
||||
strdup("Too many matching device files found");
|
||||
return ERANGE;
|
||||
}
|
||||
if (ddlpa_is_sg(o, try_path))
|
||||
have_sg = 1;
|
||||
else if (ddlpa_is_sr(o, try_path))
|
||||
have_sr = 1;
|
||||
else if (ddlpa_is_scd(o, try_path))
|
||||
have_scd = 1;
|
||||
strcpy(o->sibling_paths[o->num_siblings], try_path);
|
||||
o->sibling_rdevs[o->num_siblings] = stbuf.st_rdev;
|
||||
o->sibling_devs[o->num_siblings] = stbuf.st_dev;
|
||||
o->sibling_inodes[o->num_siblings] = stbuf.st_ino;
|
||||
|
||||
if (ddlpa_debug_mode)
|
||||
fprintf(stderr,
|
||||
"DDLPA_DEBUG: ddlpa_collect_siblings() found \"%s\"\n",
|
||||
try_path);
|
||||
|
||||
(o->num_siblings)++;
|
||||
}
|
||||
if (have_sg && have_sr && have_scd)
|
||||
return 0;
|
||||
if (o->ddlpa_flags & DDLPA_ALLOW_MISSING_SGRCD)
|
||||
return 0;
|
||||
|
||||
o->errmsg = strdup("Did not find enough siblings");
|
||||
|
||||
/* >>> add more info about busy and forbidden paths */
|
||||
|
||||
return EBUSY;
|
||||
}
|
||||
|
||||
|
||||
static int ddlpa_std_by_btl(struct ddlpa_lock *o)
|
||||
{
|
||||
int idx = 0, ret;
|
||||
char try_path[DDLPA_MAX_STD_LEN+1];
|
||||
int t_bus, t_host, t_channel, t_id, t_lun;
|
||||
|
||||
if (!o->inbtl_is_valid)
|
||||
return EFAULT;
|
||||
|
||||
while (ddlpa_enumerate(o, &idx, try_path) == 0) {
|
||||
if (!ddlpa_is_sr(o, try_path))
|
||||
continue;
|
||||
ret = ddlpa_obtain_scsi_adr(o, try_path,
|
||||
&t_bus, &t_host, &t_channel, &t_id, &t_lun);
|
||||
if (ret) {
|
||||
|
||||
/* >>> interpret error, memorize busy, no permission */
|
||||
|
||||
continue;
|
||||
}
|
||||
if (t_bus != o->in_bus || t_id != o->in_target ||
|
||||
t_lun != o->in_lun)
|
||||
continue;
|
||||
strcpy(o->std_path, try_path);
|
||||
|
||||
if (ddlpa_debug_mode)
|
||||
fprintf(stderr,
|
||||
"DDLPA_DEBUG: ddlpa_std_by_btl(%d,%d,%d) = \"%s\"\n",
|
||||
t_bus, t_id, t_lun, o->std_path);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* >>> add more info about busy and forbidden paths */
|
||||
|
||||
return ENOENT;
|
||||
}
|
||||
|
||||
|
||||
static int ddlpa_open_all(struct ddlpa_lock *o)
|
||||
{
|
||||
int i, j, ret, no_o_excl;
|
||||
|
||||
if (ddlpa_is_scsi(o, o->std_path)) {
|
||||
ret = ddlpa_collect_siblings(o);
|
||||
if (ret)
|
||||
return ret;
|
||||
for (i = 0; i < o->num_siblings; i++) {
|
||||
|
||||
/* Watch out for the main personality of the drive. */
|
||||
/* No need to occupy identical path or softlink path */
|
||||
if (o->sibling_devs[i] == o->dev &&
|
||||
o->sibling_inodes[i] == o->ino)
|
||||
continue;
|
||||
/* There may be the same rdev but different inode. */
|
||||
no_o_excl = (o->sibling_rdevs[i] == o->rdev);
|
||||
|
||||
/* Look for multiply registered device drivers with
|
||||
distinct inodes. */
|
||||
for (j = 0; j < i; j++) {
|
||||
if (o->sibling_devs[j] == o->sibling_devs[i] &&
|
||||
o->sibling_inodes[j] == o->sibling_inodes[i])
|
||||
break;
|
||||
if (o->sibling_rdevs[j] == o->sibling_rdevs[i])
|
||||
no_o_excl = 1;
|
||||
}
|
||||
if (j < i)
|
||||
continue; /* inode is already occupied */
|
||||
|
||||
ret = ddlpa_occupy(o, o->sibling_paths[i],
|
||||
&(o->sibling_fds[i]), no_o_excl);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (o->ddlpa_flags & DDLPA_OPEN_GIVEN_PATH)
|
||||
ret = ddlpa_occupy(o, o->path, &(o->fd), 0);
|
||||
else
|
||||
ret = ddlpa_occupy(o, o->std_path, &(o->fd), 0);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* >>> use fcntl() to adjust O_NONBLOCK */;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------- public -------------------- */
|
||||
|
||||
|
||||
int ddlpa_destroy(struct ddlpa_lock **lockbundle)
|
||||
{
|
||||
struct ddlpa_lock *o;
|
||||
int i;
|
||||
|
||||
o= *lockbundle;
|
||||
if (o == NULL)
|
||||
return 0;
|
||||
for (i = 0; i < o->num_siblings; i++)
|
||||
if (o->sibling_fds[i] != -1)
|
||||
close(o->sibling_fds[i]);
|
||||
if(o->fd != -1)
|
||||
close(o->fd);
|
||||
if (o->path != NULL)
|
||||
free(o->path);
|
||||
if (o->errmsg != NULL)
|
||||
free(o->errmsg);
|
||||
free((char *) o);
|
||||
*lockbundle = NULL;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int ddlpa_lock_path(char *path, int o_flags, int ddlpa_flags,
|
||||
struct ddlpa_lock **lockbundle, char **errmsg)
|
||||
{
|
||||
struct ddlpa_lock *o;
|
||||
int ret;
|
||||
|
||||
*errmsg = NULL;
|
||||
if (ddlpa_new(&o, o_flags, ddlpa_flags))
|
||||
return ENOMEM;
|
||||
*lockbundle = o;
|
||||
|
||||
o->path = strdup(path);
|
||||
if (o->path == NULL)
|
||||
return ENOMEM;
|
||||
o->path_is_valid = 1;
|
||||
|
||||
ret = ddlpa_std_by_rdev(o);
|
||||
if (ret) {
|
||||
*errmsg = strdup(
|
||||
"Cannot find equivalent of given path among standard paths");
|
||||
return ret;
|
||||
}
|
||||
ret = ddlpa_open_all(o);
|
||||
if (ret) {
|
||||
*errmsg = o->errmsg;
|
||||
o->errmsg = NULL;
|
||||
ddlpa_destroy(&o);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int ddlpa_lock_btl(int bus, int target, int lun,
|
||||
int o_flags, int ddlpa_flags,
|
||||
struct ddlpa_lock **lockbundle, char **errmsg)
|
||||
{
|
||||
struct ddlpa_lock *o;
|
||||
int ret;
|
||||
|
||||
*errmsg = NULL;
|
||||
ddlpa_flags &= ~DDLPA_OPEN_GIVEN_PATH;
|
||||
if (ddlpa_new(&o, o_flags, ddlpa_flags))
|
||||
return ENOMEM;
|
||||
*lockbundle = o;
|
||||
|
||||
o->in_bus = bus;
|
||||
o->in_target = target;
|
||||
o->in_lun = lun;
|
||||
o->inbtl_is_valid = 1;
|
||||
ret = ddlpa_std_by_btl(o);
|
||||
if (ret) {
|
||||
*errmsg = strdup(
|
||||
"Cannot find /dev/sr* with given Bus,Target,Lun");
|
||||
return ret;
|
||||
}
|
||||
ret = ddlpa_open_all(o);
|
||||
if (ret) {
|
||||
*errmsg = o->errmsg;
|
||||
o->errmsg = NULL;
|
||||
ddlpa_destroy(&o);
|
||||
return ret;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
#ifdef DDLPA_C_STANDALONE
|
||||
|
||||
/* ----------------------------- Test / Demo -------------------------- */
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
struct ddlpa_lock *lck = NULL;
|
||||
char *errmsg = NULL, *opened_path = NULL, *my_path = NULL;
|
||||
int i, ret, fd = -1, duration = -1, bus = -1, target = -1, lun = -1;
|
||||
|
||||
if (argc < 3) {
|
||||
usage:;
|
||||
fprintf(stderr, "usage: %s device_path duration\n", argv[0]);
|
||||
exit(1);
|
||||
}
|
||||
my_path = argv[1];
|
||||
sscanf(argv[2], "%d", &duration);
|
||||
if (duration < 0)
|
||||
goto usage;
|
||||
|
||||
|
||||
/* For our purpose, only O_RDWR is a suitable access mode.
|
||||
But in order to allow experiments, o_flags are freely adjustable.
|
||||
|
||||
Warning: Do _not_ set an own O_EXCL flag with the following calls !
|
||||
|
||||
(This freedom to fail may get removed in a final version.)
|
||||
*/
|
||||
if (my_path[0] != '/' && my_path[0] != '.' &&
|
||||
strchr(my_path, ',') != NULL) {
|
||||
/*
|
||||
cdrecord style dev=Bus,Target,Lun
|
||||
*/
|
||||
|
||||
sscanf(my_path, "%d,%d,%d", &bus, &target, &lun);
|
||||
ret = ddlpa_lock_btl(bus, target, lun, O_RDWR | O_LARGEFILE,
|
||||
0, &lck, &errmsg);
|
||||
} else {
|
||||
/*
|
||||
This substitutes for:
|
||||
fd = open(my_path, O_RDWR | O_EXCL | O_LARGEFILE);
|
||||
|
||||
*/
|
||||
|
||||
ret = ddlpa_lock_path(my_path, O_RDWR | O_LARGEFILE,
|
||||
0, &lck, &errmsg);
|
||||
}
|
||||
if (ret) {
|
||||
fprintf(stderr, "Cannot exclusively open '%s'\n", my_path);
|
||||
if (errmsg != NULL)
|
||||
fprintf(stderr, "Reason given : %s\n",
|
||||
errmsg);
|
||||
free(errmsg);
|
||||
fprintf(stderr, "Error condition : %d '%s'\n",
|
||||
ret, strerror(ret));
|
||||
exit(2);
|
||||
}
|
||||
fd = lck->fd;
|
||||
|
||||
printf("---------------------------------------------- Lock gained\n");
|
||||
|
||||
|
||||
/* Use fd for the usual operations on the device depicted by my_path.
|
||||
*/
|
||||
|
||||
|
||||
/* This prints an overview of the impact of the lock */
|
||||
if (lck->ddlpa_flags & DDLPA_OPEN_GIVEN_PATH)
|
||||
opened_path = lck->path;
|
||||
else
|
||||
opened_path = lck->std_path;
|
||||
printf("ddlpa: opened %s", opened_path);
|
||||
|
||||
if (strcmp(opened_path, lck->std_path) != 0)
|
||||
printf(" (an alias of '%s')", lck->std_path);
|
||||
printf("\n");
|
||||
if (lck->num_siblings > 0) {
|
||||
printf("ddlpa: opened siblings:");
|
||||
for (i = 0; i < lck->num_siblings; i++)
|
||||
if (lck->sibling_fds[i] != -1)
|
||||
printf(" %s", lck->sibling_paths[i]);
|
||||
printf("\n");
|
||||
}
|
||||
|
||||
|
||||
/* This example waits a while. So other lock candidates can collide. */
|
||||
for (i = 0; i < duration; i++) {
|
||||
sleep(1);
|
||||
fprintf(stderr, "\rslept %d seconds of %d", i + 1, duration);
|
||||
}
|
||||
fprintf(stderr, "\n");
|
||||
|
||||
|
||||
/* When finally done with the drive, this substitutes for:
|
||||
close(fd);
|
||||
*/
|
||||
if (ddlpa_destroy(&lck)) {
|
||||
/* Well, man 2 close says it can fail. */
|
||||
exit(3);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
|
||||
|
||||
#endif /* DDLPA_C_STANDALONE */
|
||||
|
107
libburn/ddlpa.h
Normal file
107
libburn/ddlpa.h
Normal file
@ -0,0 +1,107 @@
|
||||
|
||||
/* ddlpa
|
||||
Implementation of Delicate Device Locking Protocol level A.
|
||||
Copyright (C) 2007 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under any of the following licenses: GPL, LGPL, BSD. Choose one.
|
||||
|
||||
See ../doc/ddlp.txt for a description of the protocol.
|
||||
*/
|
||||
|
||||
#ifndef DDLPA_H_INCLUDED
|
||||
#define DDLPA_H_INCLUDED 1
|
||||
|
||||
|
||||
/* An upper limit for the length of standard paths and sibling paths */
|
||||
#define DDLPA_MAX_STD_LEN 15
|
||||
|
||||
/* An upper limit for the number of siblings */
|
||||
#define DDLPA_MAX_SIBLINGS 5
|
||||
|
||||
struct ddlpa_lock {
|
||||
|
||||
/* Recorded input parameters of locking call */
|
||||
char *path;
|
||||
int path_is_valid;
|
||||
int in_bus, in_target, in_lun;
|
||||
int inbtl_is_valid;
|
||||
int ddlpa_flags;
|
||||
int o_flags;
|
||||
|
||||
/* Result of locking call */
|
||||
char std_path[DDLPA_MAX_STD_LEN + 1];
|
||||
int fd;
|
||||
dev_t rdev;
|
||||
dev_t dev;
|
||||
ino_t ino;
|
||||
int host, channel, id, lun, bus;
|
||||
int hcilb_is_valid;
|
||||
int num_siblings;
|
||||
char sibling_paths[DDLPA_MAX_SIBLINGS][DDLPA_MAX_STD_LEN + 1];
|
||||
int sibling_fds[DDLPA_MAX_SIBLINGS];
|
||||
dev_t sibling_rdevs[DDLPA_MAX_SIBLINGS];
|
||||
dev_t sibling_devs[DDLPA_MAX_SIBLINGS];
|
||||
ino_t sibling_inodes[DDLPA_MAX_SIBLINGS];
|
||||
|
||||
/* Is NULL if all goes well. Else it may contain a text message. */
|
||||
char *errmsg;
|
||||
};
|
||||
|
||||
|
||||
|
||||
/** Lock a recorder by naming a device file path. Allocate a new container.
|
||||
@param path Gives the file system path of the recorder
|
||||
as known to the calling program.
|
||||
@param o_flags flags for open(2). Do not use O_EXCL here because this
|
||||
is done automatically whenever appropriate.
|
||||
Advised is O_RDWR | O_LARGEFILE, eventually | O_NDELAY.
|
||||
@param ddlpa_flags 0 = default behavior: the standard path will be opened
|
||||
and treated by fcntl(F_SETLK)
|
||||
DDLPA_OPEN_GIVEN_PATH causes the input parameter "path"
|
||||
to be used with open(2) and fcntl(2).
|
||||
DDLPA_ALLOW_MISSING_SGRCD allows to grant a lock
|
||||
although not all three, a sg, a sr and a scd device
|
||||
file have been found during sibling search. Normally
|
||||
this is counted as failure due to EBUSY.
|
||||
@param lockbundle gets allocated and then represents the locking state
|
||||
@param errmsg if *errmsg is not NULL after the call, it contains an
|
||||
error message. Then to be released by free(3).
|
||||
It is NULL in case of success or lack of memory.
|
||||
@return 0=success , else an errno compatible error number
|
||||
*/
|
||||
int ddlpa_lock_path(char *path, int o_flags, int ddlpa_flags,
|
||||
struct ddlpa_lock **lockbundle, char **errmsg);
|
||||
|
||||
|
||||
/** Lock a recorder by naming a Bus,Target,Lun number triple.
|
||||
Allocate a new container.
|
||||
@param bus parameter to match ioctl(SCSI_IOCTL_GET_BUS_NUMBER)
|
||||
@param target parameter to match ioctl(SCSI_IOCTL_GET_IDLUN) &0xff
|
||||
@param lun parameter to match ioctl(SCSI_IOCTL_GET_IDLUN) &0xff00
|
||||
@param o_flags see ddlpa_lock_path().
|
||||
@param ddlpa_flags see ddlpa_lock_path(). Flag DDLPA_OPEN_GIVEN_PATH
|
||||
will be ignored.
|
||||
@param lockbundle see ddlpa_lock_path().
|
||||
@param errmsg see ddlpa_lock_path().
|
||||
@return 0=success , else an errno compatible error number
|
||||
*/
|
||||
int ddlpa_lock_btl(int bus, int target, int lun,
|
||||
int o_flags, int ddlpa_flags,
|
||||
struct ddlpa_lock **lockbundle, char **errmsg);
|
||||
|
||||
|
||||
/** Release the lock by closing all filedescriptors and freeing memory.
|
||||
@param lockbundle the lock which is to be released.
|
||||
*lockbundle will be set to NULL by this call.
|
||||
@return 0=success , 1=failure
|
||||
*/
|
||||
int ddlpa_destroy(struct ddlpa_lock **lockbundle);
|
||||
|
||||
|
||||
|
||||
/** Definitions of macros used in above functions */
|
||||
|
||||
#define DDLPA_OPEN_GIVEN_PATH 1
|
||||
#define DDLPA_ALLOW_MISSING_SGRCD 2
|
||||
|
||||
|
||||
#endif /* DDLPA_H_INCLUDED */
|
@ -1,5 +1,14 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
2344
libburn/drive.c
2344
libburn/drive.c
File diff suppressed because it is too large
Load Diff
@ -1,15 +1,24 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __DRIVE
|
||||
#define __DRIVE
|
||||
|
||||
#include "libburn.h"
|
||||
#include "toc.h"
|
||||
#include "structure.h"
|
||||
#include <pthread.h>
|
||||
|
||||
struct burn_drive;
|
||||
struct command;
|
||||
struct mempage;
|
||||
struct scsi_mode_data;
|
||||
struct burn_speed_descriptor;
|
||||
|
||||
#define LEAD_IN 1
|
||||
#define GAP 2
|
||||
@ -41,7 +50,8 @@ unsigned int burn_drive_count(void);
|
||||
|
||||
/* ts A61007 */
|
||||
/* void burn_wait_all(void); */
|
||||
int burn_drives_are_clear(void);
|
||||
/* @param flag bit0= demand freed drives (else released drives) */
|
||||
int burn_drives_are_clear(int flag);
|
||||
|
||||
int burn_sector_length_write(struct burn_drive *d);
|
||||
int burn_track_control(struct burn_drive *d, int);
|
||||
@ -50,8 +60,10 @@ void burn_write_empty_subcode(int fd);
|
||||
void burn_drive_free(struct burn_drive *d);
|
||||
void burn_drive_free_all(void);
|
||||
|
||||
/* @param flag bit0= reset global drive list */
|
||||
int burn_drive_scan_sync(struct burn_drive_info *drives[],
|
||||
unsigned int *n_drives);
|
||||
unsigned int *n_drives, int flag);
|
||||
|
||||
void burn_disc_erase_sync(struct burn_drive *d, int fast);
|
||||
int burn_drive_get_block_types(struct burn_drive *d,
|
||||
enum burn_write_types write_type);
|
||||
@ -69,5 +81,74 @@ int burn_setup_drive(struct burn_drive *d, char *fname);
|
||||
*/
|
||||
struct burn_drive *burn_drive_finish_enum(struct burn_drive *d);
|
||||
|
||||
/* ts A61125 : media status aspects of burn_drive_grab() */
|
||||
int burn_drive_inquire_media(struct burn_drive *d);
|
||||
|
||||
/* ts A61125 : model aspects of burn_drive_release */
|
||||
int burn_drive_mark_unready(struct burn_drive *d);
|
||||
|
||||
|
||||
/* ts A61226 */
|
||||
int burn_speed_descriptor_new(struct burn_speed_descriptor **s,
|
||||
struct burn_speed_descriptor *prev,
|
||||
struct burn_speed_descriptor *next, int flag);
|
||||
|
||||
/* ts A61226 */
|
||||
/* @param flag bit0= destroy whole next-chain of descriptors */
|
||||
int burn_speed_descriptor_destroy(struct burn_speed_descriptor **s, int flag);
|
||||
|
||||
|
||||
/* ts A61226 : free dynamically allocated sub data of struct scsi_mode_data */
|
||||
int burn_mdata_free_subs(struct scsi_mode_data *m);
|
||||
|
||||
|
||||
/* ts A61230 */
|
||||
void burn_disc_format_sync(struct burn_drive *d, off_t size, int flag);
|
||||
|
||||
|
||||
/* ts A70207 : evaluate write mode related peculiarities of a disc */
|
||||
struct burn_disc_mode_demands {
|
||||
int multi_session;
|
||||
int multi_track;
|
||||
int unknown_track_size; /* 0=known, 1=unknown, 2=unknown+defaulted */
|
||||
int mixed_mode;
|
||||
int audio;
|
||||
int exotic_track;
|
||||
int block_types;
|
||||
int will_append; /* because of media state or multi session disc */
|
||||
};
|
||||
int burn_disc_get_write_mode_demands(struct burn_disc *disc,
|
||||
struct burn_write_opts *opts,
|
||||
struct burn_disc_mode_demands *result, int flag);
|
||||
|
||||
|
||||
/* ts A70924 : convert a special stdio address into fd number.
|
||||
@return >0 is a valid fd , -1 indicates unsuitable address string.
|
||||
*/
|
||||
int burn_drive__fd_from_special_adr(char *adr);
|
||||
|
||||
|
||||
/* ts A70929 : Find the drive which is being worked on by pid , tid */
|
||||
int burn_drive_find_by_thread_pid(struct burn_drive **d, pid_t pid,
|
||||
pthread_t tid);
|
||||
|
||||
|
||||
/* ts A51221 - A80731 : Whitelist inquiry functions */
|
||||
int burn_drive_is_banned(char *device_address);
|
||||
int burn_drive_whitelist_count(void);
|
||||
char *burn_drive_whitelist_item(int idx, int flag);
|
||||
|
||||
|
||||
/* ts A80801 */
|
||||
int burn_drive_is_listed(char *path, struct burn_drive **found, int flag);
|
||||
|
||||
|
||||
/* ts B00226 : Outsourced backend of burn_abort()
|
||||
@param elapsed to be subtracted from start time
|
||||
@param flag bit0= do not shutdown the library
|
||||
*/
|
||||
int burn_abort_5(int patience,
|
||||
int (*pacifier_func)(void *handle, int patience, int elapsed),
|
||||
void *handle, int elapsed, int flag);
|
||||
|
||||
#endif /* __DRIVE */
|
||||
|
855
libburn/ecma130ab.c
Normal file
855
libburn/ecma130ab.c
Normal file
@ -0,0 +1,855 @@
|
||||
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
/* ts A91016 : libburn/ecma130ab.c is the replacement for old libburn/lec.c
|
||||
|
||||
Copyright 2009, Thomas Schmitt <scdbackup@gmx.net>, libburnia-project.org
|
||||
Provided under GPL version 2 or later.
|
||||
|
||||
This code module implements the production of RSPC parity bytes (P- and Q-
|
||||
parity) and the scrambling of raw CD-ROM sectors as specified in ECMA-130:
|
||||
http://www.ecma-international.org/publications/files/ECMA-ST/Ecma-130.pdf
|
||||
|
||||
The following statements about Galois Fields have been learned mostly from
|
||||
http://www.cs.utk.edu/~plank/plank/papers/CS-96-332.pdf
|
||||
by James S. Plank after an e-mail exchange with Norbert Preining.
|
||||
|
||||
The output has been compared with the output of the old code of libburn
|
||||
which was labeled "borrowed HEAVILY from cdrdao" and claimed by Joerg
|
||||
Schilling to stem from code by Heiko Eissfeldt.
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
Note: In this text, "^" denotes exponentiation and not the binary exor
|
||||
operation. Confusingly in the C code "^" is said exor.
|
||||
Note: This is not C1, C2 which is rather mentioned in ECMA-130 Annex C and
|
||||
always performed inside the drive.
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
|
||||
RSPC resp. P- and Q-Parity
|
||||
|
||||
ECMA-130 Annex A prescribes to compute the parity bytes for P-columns and
|
||||
Q-diagonals by RSPC based on a Galois Field GF(2^8) with enumerating
|
||||
polynomials x^8+x^4+x^3+x^2+1 (i.e. 0x11d) and x^1 (i.e. 0x02).
|
||||
Bytes 12 to 2075 of a audio-sized sector get ordered in two byte words
|
||||
as 24 rows and 43 columns. Then this matrix is split into a LSB matrix
|
||||
and a MSB matrix of the same layout. Parity bytes are to be computed
|
||||
from these 8-bit values.
|
||||
2 P-bytes cover each column of 24 bytes. They get appended to the matrix
|
||||
as rows 24 and 25.
|
||||
2 Q-bytes cover each the 26 diagonals of the extended matrix.
|
||||
|
||||
Both parity byte pairs have to be computed so that extended rows or
|
||||
diagonals match this linear equation:
|
||||
H x V = (0,0)
|
||||
H is a 2-row matrix of size n matching the length of the V ectors
|
||||
[ 1 1 ... 1 1 ]
|
||||
[ x^(n-1) x^(n-2) x^1 1 ]
|
||||
Vp represents a P-row. It is a byte vector consisting of row bytes at
|
||||
position 0 to 23 and the two parity bytes which shall be determined
|
||||
at position 24 and 25. So Hp has 26 columns.
|
||||
Vq represents a Q-diagonal. It is a byte vector consisting of diagonal
|
||||
bytes at position 0 to 42 and the two parity bytes at position 43 and 44.
|
||||
So Hq has 45 columns. The Q-diagonals cover P-parity bytes.
|
||||
|
||||
By applying some high school algebra one gets the parity bytes b0, b1 of
|
||||
vector V = (n_payload_bytes, b0 , b1) as
|
||||
|
||||
b0 = ( H[n] * SUM(n_payload_bytes) - H[0..(n-1)] x n_payload_bytes )
|
||||
/ (H[n+1] - H[n])
|
||||
b1 = - SUM(n_payload_bytes) - b0
|
||||
|
||||
H[i] is the i-the element of the second row of matrix H. E.g. H[0] = x^(n-1)
|
||||
The result has to be computed by Galois field arithmetics. See below.
|
||||
|
||||
The P-parity bytes of each column get reunited as LSB and MSB of two words.
|
||||
word1 gets written to positions 1032 to 1074, word0 to 1075 to 1117.
|
||||
The Q-parity bytes of each diagonal get reunited too. word1 goes to 1118
|
||||
to 1143, word0 to 1144 to 1169.
|
||||
>>> I do not read this swap of word1 and word0 from ECMA-130 Annex A.
|
||||
>>> But the new output matches the old output only if it is done that way.
|
||||
>>> See correctness reservation below.
|
||||
|
||||
Algebra on Galois fields is the same as on Rational Numbers.
|
||||
But arithmetics is defined by operations on polynomials rather than the
|
||||
usual integer arithmetics on binary numbers.
|
||||
Addition and subtraction are identical with the binary exor operator.
|
||||
Multiplication and division would demand polynomial division, e.g. by the
|
||||
euclidian algorithm. The computing path over logarithms and powers follows
|
||||
algebra and allows to reduce the arithmetic task to table lookups, additions
|
||||
modulo 255, and exor operations. Note that the logarithms are natural
|
||||
numbers, not polynomials. They get added or subtracted by the usual addition
|
||||
(not by exor) and their polynomial power depends on their value modulo 255.
|
||||
|
||||
Needed are a logarithm table and a power table (or inverse logarithm table)
|
||||
for Galois Field GF(2^8) which will serve to perform the peculiar
|
||||
multiplication and division operation of Galois fields.
|
||||
|
||||
The power table is simply an enumeration of x^n accorting to
|
||||
GF-multiplication. It also serves as second line of matrix H for the parity
|
||||
equations:
|
||||
Hp[i] = gfpow[25-i] , i out of {0,..,25}
|
||||
Hq[i] = gfpow[44-i] , i out of {0,..,44}
|
||||
|
||||
The logarithm table is the inverse permutation of the power table.
|
||||
|
||||
Some simplifications apply to the implementation:
|
||||
In the world of Galois fields there is no difference between - and +.
|
||||
The term (H[n+1] - H[n]) is constant: 3.
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
|
||||
Scrambling
|
||||
|
||||
ECMA-130 Annex B prescribes to exor the byte stream of an audio-sized sector
|
||||
with a sequence of pseudo random bytes. It mentions polynomial x^15+x+1 and
|
||||
a 15-bit register.
|
||||
It shows a diagram of a Feedback Shift Register with 16 bit boxes, though.
|
||||
|
||||
Comparing this with explanations in
|
||||
http://www.newwaveinstruments.com/resources/articles/m_sequence_linear_feedback_shift_register_lfsr.htm
|
||||
one can recognize the diagram as a Fibonacci Implementation. But there seems
|
||||
really to be one bit box too many.
|
||||
|
||||
The difference of both lengths is expressed in function next_bit() by
|
||||
the constants 0x3fff,0x4000 for 15 bit versus 0x7fff,0x8000 for 16 bits.
|
||||
Comparing the output of both alternatives with the old scrambler output
|
||||
lets 15 bit win for now.
|
||||
|
||||
So the prescription is to start with 15 bit value 1, to use the lowest bit
|
||||
as output, to shift the bits down by one, to exor the output bit with the
|
||||
next lowest bit, and to put that exor result into bit 14 of the register.
|
||||
|
||||
-------------------------------------------------------------------------
|
||||
|
||||
|
||||
Correctness Reservation
|
||||
|
||||
In both cases, parity and scrambling, the goal for now is to replicate the
|
||||
output of the dismissed old lec.c by output which is based on published
|
||||
specs and own implementation code. Whether they comply to ECMA-130 is a
|
||||
different question which can only be answered by real test cases for
|
||||
raw CD recording.
|
||||
|
||||
Of course this implementation will be corrected so that it really complies
|
||||
to ECMA-130 as soon as evidence emerges that it does not yet.
|
||||
|
||||
*/
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
/* Power and logarithm tables for GF(2^8), parity matrices for ECMA-130.
|
||||
Generated by burn_rspc_setup_tables() and burn_rspc_print_tables().
|
||||
|
||||
The highest possible sum of gflog[] values is is 508. So the table gfpow[]
|
||||
with period 255 was manually unrolled to 509 elements to avoid one modulo
|
||||
255 operation in burn_rspc_mult().
|
||||
Proposed by D. Hugh Redelmeier.
|
||||
|
||||
*/
|
||||
|
||||
static unsigned char gfpow[509] = {
|
||||
1, 2, 4, 8, 16, 32, 64, 128, 29, 58,
|
||||
116, 232, 205, 135, 19, 38, 76, 152, 45, 90,
|
||||
180, 117, 234, 201, 143, 3, 6, 12, 24, 48,
|
||||
96, 192, 157, 39, 78, 156, 37, 74, 148, 53,
|
||||
106, 212, 181, 119, 238, 193, 159, 35, 70, 140,
|
||||
5, 10, 20, 40, 80, 160, 93, 186, 105, 210,
|
||||
185, 111, 222, 161, 95, 190, 97, 194, 153, 47,
|
||||
94, 188, 101, 202, 137, 15, 30, 60, 120, 240,
|
||||
253, 231, 211, 187, 107, 214, 177, 127, 254, 225,
|
||||
223, 163, 91, 182, 113, 226, 217, 175, 67, 134,
|
||||
17, 34, 68, 136, 13, 26, 52, 104, 208, 189,
|
||||
103, 206, 129, 31, 62, 124, 248, 237, 199, 147,
|
||||
59, 118, 236, 197, 151, 51, 102, 204, 133, 23,
|
||||
46, 92, 184, 109, 218, 169, 79, 158, 33, 66,
|
||||
132, 21, 42, 84, 168, 77, 154, 41, 82, 164,
|
||||
85, 170, 73, 146, 57, 114, 228, 213, 183, 115,
|
||||
230, 209, 191, 99, 198, 145, 63, 126, 252, 229,
|
||||
215, 179, 123, 246, 241, 255, 227, 219, 171, 75,
|
||||
150, 49, 98, 196, 149, 55, 110, 220, 165, 87,
|
||||
174, 65, 130, 25, 50, 100, 200, 141, 7, 14,
|
||||
28, 56, 112, 224, 221, 167, 83, 166, 81, 162,
|
||||
89, 178, 121, 242, 249, 239, 195, 155, 43, 86,
|
||||
172, 69, 138, 9, 18, 36, 72, 144, 61, 122,
|
||||
244, 245, 247, 243, 251, 235, 203, 139, 11, 22,
|
||||
44, 88, 176, 125, 250, 233, 207, 131, 27, 54,
|
||||
108, 216, 173, 71, 142,
|
||||
1, 2, 4, 8, 16, 32, 64, 128, 29, 58,
|
||||
116, 232, 205, 135, 19, 38, 76, 152, 45, 90,
|
||||
180, 117, 234, 201, 143, 3, 6, 12, 24, 48,
|
||||
96, 192, 157, 39, 78, 156, 37, 74, 148, 53,
|
||||
106, 212, 181, 119, 238, 193, 159, 35, 70, 140,
|
||||
5, 10, 20, 40, 80, 160, 93, 186, 105, 210,
|
||||
185, 111, 222, 161, 95, 190, 97, 194, 153, 47,
|
||||
94, 188, 101, 202, 137, 15, 30, 60, 120, 240,
|
||||
253, 231, 211, 187, 107, 214, 177, 127, 254, 225,
|
||||
223, 163, 91, 182, 113, 226, 217, 175, 67, 134,
|
||||
17, 34, 68, 136, 13, 26, 52, 104, 208, 189,
|
||||
103, 206, 129, 31, 62, 124, 248, 237, 199, 147,
|
||||
59, 118, 236, 197, 151, 51, 102, 204, 133, 23,
|
||||
46, 92, 184, 109, 218, 169, 79, 158, 33, 66,
|
||||
132, 21, 42, 84, 168, 77, 154, 41, 82, 164,
|
||||
85, 170, 73, 146, 57, 114, 228, 213, 183, 115,
|
||||
230, 209, 191, 99, 198, 145, 63, 126, 252, 229,
|
||||
215, 179, 123, 246, 241, 255, 227, 219, 171, 75,
|
||||
150, 49, 98, 196, 149, 55, 110, 220, 165, 87,
|
||||
174, 65, 130, 25, 50, 100, 200, 141, 7, 14,
|
||||
28, 56, 112, 224, 221, 167, 83, 166, 81, 162,
|
||||
89, 178, 121, 242, 249, 239, 195, 155, 43, 86,
|
||||
172, 69, 138, 9, 18, 36, 72, 144, 61, 122,
|
||||
244, 245, 247, 243, 251, 235, 203, 139, 11, 22,
|
||||
44, 88, 176, 125, 250, 233, 207, 131, 27, 54,
|
||||
108, 216, 173, 71,
|
||||
};
|
||||
|
||||
static unsigned char gflog[256] = {
|
||||
0, 0, 1, 25, 2, 50, 26, 198, 3, 223,
|
||||
51, 238, 27, 104, 199, 75, 4, 100, 224, 14,
|
||||
52, 141, 239, 129, 28, 193, 105, 248, 200, 8,
|
||||
76, 113, 5, 138, 101, 47, 225, 36, 15, 33,
|
||||
53, 147, 142, 218, 240, 18, 130, 69, 29, 181,
|
||||
194, 125, 106, 39, 249, 185, 201, 154, 9, 120,
|
||||
77, 228, 114, 166, 6, 191, 139, 98, 102, 221,
|
||||
48, 253, 226, 152, 37, 179, 16, 145, 34, 136,
|
||||
54, 208, 148, 206, 143, 150, 219, 189, 241, 210,
|
||||
19, 92, 131, 56, 70, 64, 30, 66, 182, 163,
|
||||
195, 72, 126, 110, 107, 58, 40, 84, 250, 133,
|
||||
186, 61, 202, 94, 155, 159, 10, 21, 121, 43,
|
||||
78, 212, 229, 172, 115, 243, 167, 87, 7, 112,
|
||||
192, 247, 140, 128, 99, 13, 103, 74, 222, 237,
|
||||
49, 197, 254, 24, 227, 165, 153, 119, 38, 184,
|
||||
180, 124, 17, 68, 146, 217, 35, 32, 137, 46,
|
||||
55, 63, 209, 91, 149, 188, 207, 205, 144, 135,
|
||||
151, 178, 220, 252, 190, 97, 242, 86, 211, 171,
|
||||
20, 42, 93, 158, 132, 60, 57, 83, 71, 109,
|
||||
65, 162, 31, 45, 67, 216, 183, 123, 164, 118,
|
||||
196, 23, 73, 236, 127, 12, 111, 246, 108, 161,
|
||||
59, 82, 41, 157, 85, 170, 251, 96, 134, 177,
|
||||
187, 204, 62, 90, 203, 89, 95, 176, 156, 169,
|
||||
160, 81, 11, 245, 22, 235, 122, 117, 44, 215,
|
||||
79, 174, 213, 233, 230, 231, 173, 232, 116, 214,
|
||||
244, 234, 168, 80, 88, 175
|
||||
};
|
||||
|
||||
|
||||
#define Libburn_use_h_matriceS 1
|
||||
|
||||
#ifdef Libburn_use_h_matriceS
|
||||
|
||||
/* On my AMD 2x64 bit 3000 MHz processor h[i] costs about 7 % more time
|
||||
than using gfpow[25-i] resp. gfpow[44-1]. I blame this on the more
|
||||
condensed data representation which slightly increases the rate of cache
|
||||
hits.
|
||||
Nevertheless this effect is very likely depending on the exact cache
|
||||
size and architecture. In general, using h[] saves more than 8000
|
||||
subtractions per sector.
|
||||
*/
|
||||
|
||||
/* Parity matrices H as prescribed by ECMA-130 Annex A.
|
||||
Actually just reverted order start pieces of gfpow[].
|
||||
*/
|
||||
static unsigned char h26[26] = {
|
||||
3, 143, 201, 234, 117, 180, 90, 45, 152, 76,
|
||||
38, 19, 135, 205, 232, 116, 58, 29, 128, 64,
|
||||
32, 16, 8, 4, 2, 1,
|
||||
};
|
||||
|
||||
static unsigned char h45[45] = {
|
||||
238, 119, 181, 212, 106, 53, 148, 74, 37, 156,
|
||||
78, 39, 157, 192, 96, 48, 24, 12, 6, 3,
|
||||
143, 201, 234, 117, 180, 90, 45, 152, 76, 38,
|
||||
19, 135, 205, 232, 116, 58, 29, 128, 64, 32,
|
||||
16, 8, 4, 2, 1,
|
||||
};
|
||||
|
||||
#endif /* Libburn_use_h_matriceS */
|
||||
|
||||
|
||||
/* Pseudo-random bytes which of course are exactly the same as with the
|
||||
previously used code.
|
||||
Generated by function print_ecma_130_scrambler().
|
||||
*/
|
||||
static unsigned char ecma_130_annex_b[2340] = {
|
||||
1, 128, 0, 96, 0, 40, 0, 30, 128, 8,
|
||||
96, 6, 168, 2, 254, 129, 128, 96, 96, 40,
|
||||
40, 30, 158, 136, 104, 102, 174, 170, 252, 127,
|
||||
1, 224, 0, 72, 0, 54, 128, 22, 224, 14,
|
||||
200, 4, 86, 131, 126, 225, 224, 72, 72, 54,
|
||||
182, 150, 246, 238, 198, 204, 82, 213, 253, 159,
|
||||
1, 168, 0, 126, 128, 32, 96, 24, 40, 10,
|
||||
158, 135, 40, 98, 158, 169, 168, 126, 254, 160,
|
||||
64, 120, 48, 34, 148, 25, 175, 74, 252, 55,
|
||||
1, 214, 128, 94, 224, 56, 72, 18, 182, 141,
|
||||
182, 229, 182, 203, 54, 215, 86, 222, 190, 216,
|
||||
112, 90, 164, 59, 59, 83, 83, 125, 253, 225,
|
||||
129, 136, 96, 102, 168, 42, 254, 159, 0, 104,
|
||||
0, 46, 128, 28, 96, 9, 232, 6, 206, 130,
|
||||
212, 97, 159, 104, 104, 46, 174, 156, 124, 105,
|
||||
225, 238, 200, 76, 86, 181, 254, 247, 0, 70,
|
||||
128, 50, 224, 21, 136, 15, 38, 132, 26, 227,
|
||||
75, 9, 247, 70, 198, 178, 210, 245, 157, 135,
|
||||
41, 162, 158, 249, 168, 66, 254, 177, 128, 116,
|
||||
96, 39, 104, 26, 174, 139, 60, 103, 81, 234,
|
||||
188, 79, 49, 244, 20, 71, 79, 114, 180, 37,
|
||||
183, 91, 54, 187, 86, 243, 126, 197, 224, 83,
|
||||
8, 61, 198, 145, 146, 236, 109, 141, 237, 165,
|
||||
141, 187, 37, 179, 91, 53, 251, 87, 3, 126,
|
||||
129, 224, 96, 72, 40, 54, 158, 150, 232, 110,
|
||||
206, 172, 84, 125, 255, 97, 128, 40, 96, 30,
|
||||
168, 8, 126, 134, 160, 98, 248, 41, 130, 158,
|
||||
225, 168, 72, 126, 182, 160, 118, 248, 38, 194,
|
||||
154, 209, 171, 28, 127, 73, 224, 54, 200, 22,
|
||||
214, 142, 222, 228, 88, 75, 122, 183, 99, 54,
|
||||
169, 214, 254, 222, 192, 88, 80, 58, 188, 19,
|
||||
49, 205, 212, 85, 159, 127, 40, 32, 30, 152,
|
||||
8, 106, 134, 175, 34, 252, 25, 129, 202, 224,
|
||||
87, 8, 62, 134, 144, 98, 236, 41, 141, 222,
|
||||
229, 152, 75, 42, 183, 95, 54, 184, 22, 242,
|
||||
142, 197, 164, 83, 59, 125, 211, 97, 157, 232,
|
||||
105, 142, 174, 228, 124, 75, 97, 247, 104, 70,
|
||||
174, 178, 252, 117, 129, 231, 32, 74, 152, 55,
|
||||
42, 150, 159, 46, 232, 28, 78, 137, 244, 102,
|
||||
199, 106, 210, 175, 29, 188, 9, 177, 198, 244,
|
||||
82, 199, 125, 146, 161, 173, 184, 125, 178, 161,
|
||||
181, 184, 119, 50, 166, 149, 186, 239, 51, 12,
|
||||
21, 197, 207, 19, 20, 13, 207, 69, 148, 51,
|
||||
47, 85, 220, 63, 25, 208, 10, 220, 7, 25,
|
||||
194, 138, 209, 167, 28, 122, 137, 227, 38, 201,
|
||||
218, 214, 219, 30, 219, 72, 91, 118, 187, 102,
|
||||
243, 106, 197, 239, 19, 12, 13, 197, 197, 147,
|
||||
19, 45, 205, 221, 149, 153, 175, 42, 252, 31,
|
||||
1, 200, 0, 86, 128, 62, 224, 16, 72, 12,
|
||||
54, 133, 214, 227, 30, 201, 200, 86, 214, 190,
|
||||
222, 240, 88, 68, 58, 179, 83, 53, 253, 215,
|
||||
1, 158, 128, 104, 96, 46, 168, 28, 126, 137,
|
||||
224, 102, 200, 42, 214, 159, 30, 232, 8, 78,
|
||||
134, 180, 98, 247, 105, 134, 174, 226, 252, 73,
|
||||
129, 246, 224, 70, 200, 50, 214, 149, 158, 239,
|
||||
40, 76, 30, 181, 200, 119, 22, 166, 142, 250,
|
||||
228, 67, 11, 113, 199, 100, 82, 171, 125, 191,
|
||||
97, 176, 40, 116, 30, 167, 72, 122, 182, 163,
|
||||
54, 249, 214, 194, 222, 209, 152, 92, 106, 185,
|
||||
239, 50, 204, 21, 149, 207, 47, 20, 28, 15,
|
||||
73, 196, 54, 211, 86, 221, 254, 217, 128, 90,
|
||||
224, 59, 8, 19, 70, 141, 242, 229, 133, 139,
|
||||
35, 39, 89, 218, 186, 219, 51, 27, 85, 203,
|
||||
127, 23, 96, 14, 168, 4, 126, 131, 96, 97,
|
||||
232, 40, 78, 158, 180, 104, 119, 110, 166, 172,
|
||||
122, 253, 227, 1, 137, 192, 102, 208, 42, 220,
|
||||
31, 25, 200, 10, 214, 135, 30, 226, 136, 73,
|
||||
166, 182, 250, 246, 195, 6, 209, 194, 220, 81,
|
||||
153, 252, 106, 193, 239, 16, 76, 12, 53, 197,
|
||||
215, 19, 30, 141, 200, 101, 150, 171, 46, 255,
|
||||
92, 64, 57, 240, 18, 196, 13, 147, 69, 173,
|
||||
243, 61, 133, 209, 163, 28, 121, 201, 226, 214,
|
||||
201, 158, 214, 232, 94, 206, 184, 84, 114, 191,
|
||||
101, 176, 43, 52, 31, 87, 72, 62, 182, 144,
|
||||
118, 236, 38, 205, 218, 213, 155, 31, 43, 72,
|
||||
31, 118, 136, 38, 230, 154, 202, 235, 23, 15,
|
||||
78, 132, 52, 99, 87, 105, 254, 174, 192, 124,
|
||||
80, 33, 252, 24, 65, 202, 176, 87, 52, 62,
|
||||
151, 80, 110, 188, 44, 113, 221, 228, 89, 139,
|
||||
122, 231, 99, 10, 169, 199, 62, 210, 144, 93,
|
||||
172, 57, 189, 210, 241, 157, 132, 105, 163, 110,
|
||||
249, 236, 66, 205, 241, 149, 132, 111, 35, 108,
|
||||
25, 237, 202, 205, 151, 21, 174, 143, 60, 100,
|
||||
17, 235, 76, 79, 117, 244, 39, 7, 90, 130,
|
||||
187, 33, 179, 88, 117, 250, 167, 3, 58, 129,
|
||||
211, 32, 93, 216, 57, 154, 146, 235, 45, 143,
|
||||
93, 164, 57, 187, 82, 243, 125, 133, 225, 163,
|
||||
8, 121, 198, 162, 210, 249, 157, 130, 233, 161,
|
||||
142, 248, 100, 66, 171, 113, 191, 100, 112, 43,
|
||||
100, 31, 107, 72, 47, 118, 156, 38, 233, 218,
|
||||
206, 219, 20, 91, 79, 123, 116, 35, 103, 89,
|
||||
234, 186, 207, 51, 20, 21, 207, 79, 20, 52,
|
||||
15, 87, 68, 62, 179, 80, 117, 252, 39, 1,
|
||||
218, 128, 91, 32, 59, 88, 19, 122, 141, 227,
|
||||
37, 137, 219, 38, 219, 90, 219, 123, 27, 99,
|
||||
75, 105, 247, 110, 198, 172, 82, 253, 253, 129,
|
||||
129, 160, 96, 120, 40, 34, 158, 153, 168, 106,
|
||||
254, 175, 0, 124, 0, 33, 192, 24, 80, 10,
|
||||
188, 7, 49, 194, 148, 81, 175, 124, 124, 33,
|
||||
225, 216, 72, 90, 182, 187, 54, 243, 86, 197,
|
||||
254, 211, 0, 93, 192, 57, 144, 18, 236, 13,
|
||||
141, 197, 165, 147, 59, 45, 211, 93, 157, 249,
|
||||
169, 130, 254, 225, 128, 72, 96, 54, 168, 22,
|
||||
254, 142, 192, 100, 80, 43, 124, 31, 97, 200,
|
||||
40, 86, 158, 190, 232, 112, 78, 164, 52, 123,
|
||||
87, 99, 126, 169, 224, 126, 200, 32, 86, 152,
|
||||
62, 234, 144, 79, 44, 52, 29, 215, 73, 158,
|
||||
182, 232, 118, 206, 166, 212, 122, 223, 99, 24,
|
||||
41, 202, 158, 215, 40, 94, 158, 184, 104, 114,
|
||||
174, 165, 188, 123, 49, 227, 84, 73, 255, 118,
|
||||
192, 38, 208, 26, 220, 11, 25, 199, 74, 210,
|
||||
183, 29, 182, 137, 182, 230, 246, 202, 198, 215,
|
||||
18, 222, 141, 152, 101, 170, 171, 63, 63, 80,
|
||||
16, 60, 12, 17, 197, 204, 83, 21, 253, 207,
|
||||
1, 148, 0, 111, 64, 44, 48, 29, 212, 9,
|
||||
159, 70, 232, 50, 206, 149, 148, 111, 47, 108,
|
||||
28, 45, 201, 221, 150, 217, 174, 218, 252, 91,
|
||||
1, 251, 64, 67, 112, 49, 228, 20, 75, 79,
|
||||
119, 116, 38, 167, 90, 250, 187, 3, 51, 65,
|
||||
213, 240, 95, 4, 56, 3, 82, 129, 253, 160,
|
||||
65, 184, 48, 114, 148, 37, 175, 91, 60, 59,
|
||||
81, 211, 124, 93, 225, 249, 136, 66, 230, 177,
|
||||
138, 244, 103, 7, 106, 130, 175, 33, 188, 24,
|
||||
113, 202, 164, 87, 59, 126, 147, 96, 109, 232,
|
||||
45, 142, 157, 164, 105, 187, 110, 243, 108, 69,
|
||||
237, 243, 13, 133, 197, 163, 19, 57, 205, 210,
|
||||
213, 157, 159, 41, 168, 30, 254, 136, 64, 102,
|
||||
176, 42, 244, 31, 7, 72, 2, 182, 129, 182,
|
||||
224, 118, 200, 38, 214, 154, 222, 235, 24, 79,
|
||||
74, 180, 55, 55, 86, 150, 190, 238, 240, 76,
|
||||
68, 53, 243, 87, 5, 254, 131, 0, 97, 192,
|
||||
40, 80, 30, 188, 8, 113, 198, 164, 82, 251,
|
||||
125, 131, 97, 161, 232, 120, 78, 162, 180, 121,
|
||||
183, 98, 246, 169, 134, 254, 226, 192, 73, 144,
|
||||
54, 236, 22, 205, 206, 213, 148, 95, 47, 120,
|
||||
28, 34, 137, 217, 166, 218, 250, 219, 3, 27,
|
||||
65, 203, 112, 87, 100, 62, 171, 80, 127, 124,
|
||||
32, 33, 216, 24, 90, 138, 187, 39, 51, 90,
|
||||
149, 251, 47, 3, 92, 1, 249, 192, 66, 208,
|
||||
49, 156, 20, 105, 207, 110, 212, 44, 95, 93,
|
||||
248, 57, 130, 146, 225, 173, 136, 125, 166, 161,
|
||||
186, 248, 115, 2, 165, 193, 187, 16, 115, 76,
|
||||
37, 245, 219, 7, 27, 66, 139, 113, 167, 100,
|
||||
122, 171, 99, 63, 105, 208, 46, 220, 28, 89,
|
||||
201, 250, 214, 195, 30, 209, 200, 92, 86, 185,
|
||||
254, 242, 192, 69, 144, 51, 44, 21, 221, 207,
|
||||
25, 148, 10, 239, 71, 12, 50, 133, 213, 163,
|
||||
31, 57, 200, 18, 214, 141, 158, 229, 168, 75,
|
||||
62, 183, 80, 118, 188, 38, 241, 218, 196, 91,
|
||||
19, 123, 77, 227, 117, 137, 231, 38, 202, 154,
|
||||
215, 43, 30, 159, 72, 104, 54, 174, 150, 252,
|
||||
110, 193, 236, 80, 77, 252, 53, 129, 215, 32,
|
||||
94, 152, 56, 106, 146, 175, 45, 188, 29, 177,
|
||||
201, 180, 86, 247, 126, 198, 160, 82, 248, 61,
|
||||
130, 145, 161, 172, 120, 125, 226, 161, 137, 184,
|
||||
102, 242, 170, 197, 191, 19, 48, 13, 212, 5,
|
||||
159, 67, 40, 49, 222, 148, 88, 111, 122, 172,
|
||||
35, 61, 217, 209, 154, 220, 107, 25, 239, 74,
|
||||
204, 55, 21, 214, 143, 30, 228, 8, 75, 70,
|
||||
183, 114, 246, 165, 134, 251, 34, 195, 89, 145,
|
||||
250, 236, 67, 13, 241, 197, 132, 83, 35, 125,
|
||||
217, 225, 154, 200, 107, 22, 175, 78, 252, 52,
|
||||
65, 215, 112, 94, 164, 56, 123, 82, 163, 125,
|
||||
185, 225, 178, 200, 117, 150, 167, 46, 250, 156,
|
||||
67, 41, 241, 222, 196, 88, 83, 122, 189, 227,
|
||||
49, 137, 212, 102, 223, 106, 216, 47, 26, 156,
|
||||
11, 41, 199, 94, 210, 184, 93, 178, 185, 181,
|
||||
178, 247, 53, 134, 151, 34, 238, 153, 140, 106,
|
||||
229, 239, 11, 12, 7, 69, 194, 179, 17, 181,
|
||||
204, 119, 21, 230, 143, 10, 228, 7, 11, 66,
|
||||
135, 113, 162, 164, 121, 187, 98, 243, 105, 133,
|
||||
238, 227, 12, 73, 197, 246, 211, 6, 221, 194,
|
||||
217, 145, 154, 236, 107, 13, 239, 69, 140, 51,
|
||||
37, 213, 219, 31, 27, 72, 11, 118, 135, 102,
|
||||
226, 170, 201, 191, 22, 240, 14, 196, 4, 83,
|
||||
67, 125, 241, 225, 132, 72, 99, 118, 169, 230,
|
||||
254, 202, 192, 87, 16, 62, 140, 16, 101, 204,
|
||||
43, 21, 223, 79, 24, 52, 10, 151, 71, 46,
|
||||
178, 156, 117, 169, 231, 62, 202, 144, 87, 44,
|
||||
62, 157, 208, 105, 156, 46, 233, 220, 78, 217,
|
||||
244, 90, 199, 123, 18, 163, 77, 185, 245, 178,
|
||||
199, 53, 146, 151, 45, 174, 157, 188, 105, 177,
|
||||
238, 244, 76, 71, 117, 242, 167, 5, 186, 131,
|
||||
51, 33, 213, 216, 95, 26, 184, 11, 50, 135,
|
||||
85, 162, 191, 57, 176, 18, 244, 13, 135, 69,
|
||||
162, 179, 57, 181, 210, 247, 29, 134, 137, 162,
|
||||
230, 249, 138, 194, 231, 17, 138, 140, 103, 37,
|
||||
234, 155, 15, 43, 68, 31, 115, 72, 37, 246,
|
||||
155, 6, 235, 66, 207, 113, 148, 36, 111, 91,
|
||||
108, 59, 109, 211, 109, 157, 237, 169, 141, 190,
|
||||
229, 176, 75, 52, 55, 87, 86, 190, 190, 240,
|
||||
112, 68, 36, 51, 91, 85, 251, 127, 3, 96,
|
||||
1, 232, 0, 78, 128, 52, 96, 23, 104, 14,
|
||||
174, 132, 124, 99, 97, 233, 232, 78, 206, 180,
|
||||
84, 119, 127, 102, 160, 42, 248, 31, 2, 136,
|
||||
1, 166, 128, 122, 224, 35, 8, 25, 198, 138,
|
||||
210, 231, 29, 138, 137, 167, 38, 250, 154, 195,
|
||||
43, 17, 223, 76, 88, 53, 250, 151, 3, 46,
|
||||
129, 220, 96, 89, 232, 58, 206, 147, 20, 109,
|
||||
207, 109, 148, 45, 175, 93, 188, 57, 177, 210,
|
||||
244, 93, 135, 121, 162, 162, 249, 185, 130, 242,
|
||||
225, 133, 136, 99, 38, 169, 218, 254, 219, 0,
|
||||
91, 64, 59, 112, 19, 100, 13, 235, 69, 143,
|
||||
115, 36, 37, 219, 91, 27, 123, 75, 99, 119,
|
||||
105, 230, 174, 202, 252, 87, 1, 254, 128, 64,
|
||||
96, 48, 40, 20, 30, 143, 72, 100, 54, 171,
|
||||
86, 255, 126, 192, 32, 80, 24, 60, 10, 145,
|
||||
199, 44, 82, 157, 253, 169, 129, 190, 224, 112,
|
||||
72, 36, 54, 155, 86, 235, 126, 207, 96, 84,
|
||||
40, 63, 94, 144, 56, 108, 18, 173, 205, 189,
|
||||
149, 177, 175, 52, 124, 23, 97, 206, 168, 84,
|
||||
126, 191, 96, 112, 40, 36, 30, 155, 72, 107,
|
||||
118, 175, 102, 252, 42, 193, 223, 16, 88, 12,
|
||||
58, 133, 211, 35, 29, 217, 201, 154, 214, 235,
|
||||
30, 207, 72, 84, 54, 191, 86, 240, 62, 196,
|
||||
16, 83, 76, 61, 245, 209, 135, 28, 98, 137,
|
||||
233, 166, 206, 250, 212, 67, 31, 113, 200, 36,
|
||||
86, 155, 126, 235, 96, 79, 104, 52, 46, 151,
|
||||
92, 110, 185, 236, 114, 205, 229, 149, 139, 47,
|
||||
39, 92, 26, 185, 203, 50, 215, 85, 158, 191,
|
||||
40, 112, 30, 164, 8, 123, 70, 163, 114, 249,
|
||||
229, 130, 203, 33, 151, 88, 110, 186, 172, 115,
|
||||
61, 229, 209, 139, 28, 103, 73, 234, 182, 207,
|
||||
54, 212, 22, 223, 78, 216, 52, 90, 151, 123,
|
||||
46, 163, 92, 121, 249, 226, 194, 201, 145, 150,
|
||||
236, 110, 205, 236, 85, 141, 255, 37, 128, 27,
|
||||
32, 11, 88, 7, 122, 130, 163, 33, 185, 216,
|
||||
114, 218, 165, 155, 59, 43, 83, 95, 125, 248,
|
||||
33, 130, 152, 97, 170, 168, 127, 62, 160, 16,
|
||||
120, 12, 34, 133, 217, 163, 26, 249, 203, 2,
|
||||
215, 65, 158, 176, 104, 116, 46, 167, 92, 122,
|
||||
185, 227, 50, 201, 213, 150, 223, 46, 216, 28,
|
||||
90, 137, 251, 38, 195, 90, 209, 251, 28, 67,
|
||||
73, 241, 246, 196, 70, 211, 114, 221, 229, 153
|
||||
};
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
/* This is the new implementation of P- and Q-parity generation.
|
||||
It needs about the same computing time as the old implementation (both
|
||||
with gcc -O2 on AMD 64 bit). Measurements indicate that about 280 MIPS
|
||||
are needed for 48x CD speed (7.1 MB/s).
|
||||
*/
|
||||
|
||||
static unsigned char burn_rspc_mult(unsigned char a, unsigned char b)
|
||||
{
|
||||
if (a == 0 || b == 0)
|
||||
return 0;
|
||||
/* Optimization of (a == 0 || b == 0) by D. Hugh Redelmeier
|
||||
if((((int)a - 1) | ((int)b - 1)) < 0)
|
||||
return 0;
|
||||
*/
|
||||
|
||||
return gfpow[gflog[a] + gflog[b]];
|
||||
/* % 255 not necessary because gfpow is unrolled up to index 510 */
|
||||
}
|
||||
|
||||
|
||||
/* Divide by polynomial 0x03. Derived from burn_rspc_div() and using the
|
||||
unrolled size of the gfpow[] array.
|
||||
*/
|
||||
static unsigned char burn_rspc_div_3(unsigned char a)
|
||||
{
|
||||
if (a == 0)
|
||||
return 0;
|
||||
return gfpow[230 + gflog[a]];
|
||||
}
|
||||
|
||||
|
||||
static void burn_rspc_p0p1(unsigned char *sector, int col,
|
||||
unsigned char *p0_lsb, unsigned char *p0_msb,
|
||||
unsigned char *p1_lsb, unsigned char *p1_msb)
|
||||
{
|
||||
unsigned char *start, b;
|
||||
unsigned int i, sum_v_lsb = 0, sum_v_msb = 0;
|
||||
unsigned int hxv_lsb = 0, hxv_msb = 0;
|
||||
|
||||
start = sector + 12 + 2 * col;
|
||||
for(i = 0; i < 24; i++) {
|
||||
b = *start;
|
||||
sum_v_lsb ^= b;
|
||||
|
||||
#ifdef Libburn_use_h_matriceS
|
||||
hxv_lsb ^= burn_rspc_mult(b, h26[i]);
|
||||
#else
|
||||
hxv_lsb ^= burn_rspc_mult(b, gfpow[25 - i]);
|
||||
#endif
|
||||
|
||||
b = *(start + 1);
|
||||
sum_v_msb ^= b;
|
||||
|
||||
#ifdef Libburn_use_h_matriceS
|
||||
hxv_msb ^= burn_rspc_mult(b, h26[i]);
|
||||
#else
|
||||
hxv_msb ^= burn_rspc_mult(b, gfpow[25 - i]);
|
||||
#endif
|
||||
|
||||
start += 86;
|
||||
}
|
||||
|
||||
/* 3 = gfpow[1] ^ gfpow[0] , 2 = gfpow[1] */
|
||||
*p0_lsb = burn_rspc_div_3(burn_rspc_mult(2, sum_v_lsb) ^ hxv_lsb);
|
||||
*p0_msb = burn_rspc_div_3(burn_rspc_mult(2, sum_v_msb) ^ hxv_msb);
|
||||
*p1_lsb = sum_v_lsb ^ *p0_lsb;
|
||||
*p1_msb = sum_v_msb ^ *p0_msb;
|
||||
}
|
||||
|
||||
|
||||
void burn_rspc_parity_p(unsigned char *sector)
|
||||
{
|
||||
int i;
|
||||
unsigned char p0_lsb, p0_msb, p1_lsb, p1_msb;
|
||||
|
||||
/* Loop over P columns */
|
||||
for(i = 0; i < 43; i++) {
|
||||
burn_rspc_p0p1(sector, i, &p0_lsb, &p0_msb, &p1_lsb, &p1_msb);
|
||||
sector[2162 + 2 * i] = p0_lsb;
|
||||
sector[2162 + 2 * i + 1] = p0_msb;
|
||||
sector[2076 + 2 * i] = p1_lsb;
|
||||
sector[2076 + 2 * i + 1] = p1_msb;
|
||||
|
||||
#ifdef Libburn_with_lec_generatoR
|
||||
if(verbous) {
|
||||
printf("p %2d : %2.2X %2.2X ", i,
|
||||
(unsigned int) p0_lsb, (unsigned int) p0_msb);
|
||||
printf("%2.2X %2.2X ",
|
||||
(unsigned int) p1_lsb, (unsigned int) p1_msb);
|
||||
printf("-> %d,%d\n", 2162 + 2 * i, 2076 + 2 * i);
|
||||
}
|
||||
#endif /* Libburn_with_lec_generatoR */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
static void burn_rspc_q0q1(unsigned char *sector, int diag,
|
||||
unsigned char *q0_lsb, unsigned char *q0_msb,
|
||||
unsigned char *q1_lsb, unsigned char *q1_msb)
|
||||
{
|
||||
unsigned char *start, b;
|
||||
unsigned int i, idx, sum_v_lsb = 0, sum_v_msb = 0;
|
||||
unsigned int hxv_lsb = 0, hxv_msb = 0;
|
||||
|
||||
start = sector + 12;
|
||||
idx = 2 * 43 * diag;
|
||||
for(i = 0; i < 43; i++) {
|
||||
if (idx >= 2236)
|
||||
idx -= 2236;
|
||||
b = start[idx];
|
||||
sum_v_lsb ^= b;
|
||||
|
||||
#ifdef Libburn_use_h_matriceS
|
||||
hxv_lsb ^= burn_rspc_mult(b, h45[i]);
|
||||
#else
|
||||
hxv_lsb ^= burn_rspc_mult(b, gfpow[44 - i]);
|
||||
#endif
|
||||
|
||||
b = start[idx + 1];
|
||||
sum_v_msb ^= b;
|
||||
|
||||
#ifdef Libburn_use_h_matriceS
|
||||
hxv_msb ^= burn_rspc_mult(b, h45[i]);
|
||||
#else
|
||||
hxv_msb ^= burn_rspc_mult(b, gfpow[44 - i]);
|
||||
#endif
|
||||
|
||||
idx += 88;
|
||||
}
|
||||
/* 3 = gfpow[1] ^ gfpow[0] , 2 = gfpow[1] */
|
||||
*q0_lsb = burn_rspc_div_3(burn_rspc_mult(2, sum_v_lsb) ^ hxv_lsb);
|
||||
*q0_msb = burn_rspc_div_3(burn_rspc_mult(2, sum_v_msb) ^ hxv_msb);
|
||||
*q1_lsb = sum_v_lsb ^ *q0_lsb;
|
||||
*q1_msb = sum_v_msb ^ *q0_msb;
|
||||
}
|
||||
|
||||
|
||||
void burn_rspc_parity_q(unsigned char *sector)
|
||||
{
|
||||
int i;
|
||||
unsigned char q0_lsb, q0_msb, q1_lsb, q1_msb;
|
||||
|
||||
/* Loop over Q diagonals */
|
||||
for(i = 0; i < 26; i++) {
|
||||
burn_rspc_q0q1(sector, i, &q0_lsb, &q0_msb, &q1_lsb, &q1_msb);
|
||||
sector[2300 + 2 * i] = q0_lsb;
|
||||
sector[2300 + 2 * i + 1] = q0_msb;
|
||||
sector[2248 + 2 * i] = q1_lsb;
|
||||
sector[2248 + 2 * i + 1] = q1_msb;
|
||||
|
||||
#ifdef Libburn_with_lec_generatoR
|
||||
if(verbous) {
|
||||
printf("q %2d : %2.2X %2.2X ", i,
|
||||
(unsigned int) q0_lsb, (unsigned int) q0_msb);
|
||||
printf("%2.2X %2.2X ",
|
||||
(unsigned int) q1_lsb, (unsigned int) q1_msb);
|
||||
printf("-> %d,%d\n", 2300 + 2 * i, 2248 + 2 * i);
|
||||
}
|
||||
#endif /* Libburn_with_lec_generatoR */
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
/* The new implementation of the ECMA-130 Annex B scrambler.
|
||||
It is totally unoptimized. One should make use of larger word operations.
|
||||
Measurements indicate that about 50 MIPS are needed for 48x CD speed.
|
||||
*/
|
||||
|
||||
void burn_ecma130_scramble(unsigned char *sector)
|
||||
{
|
||||
int i;
|
||||
unsigned char *s;
|
||||
|
||||
s = sector + 12;
|
||||
for (i = 0; i < 2340; i++)
|
||||
s[i] ^= ecma_130_annex_b[i];
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
|
||||
/* The following code is not needed for libburn but rather documents the
|
||||
origin of the tables above. In libburn it will not be compiled.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef Libburn_with_lec_generatoR
|
||||
|
||||
|
||||
/* This function produced the content of gflog[] and gfpow[]
|
||||
*/
|
||||
static int burn_rspc_setup_tables(void)
|
||||
{
|
||||
unsigned int b, l;
|
||||
|
||||
memset(gflog, 0, sizeof(gflog));
|
||||
memset(gfpow, 0, sizeof(gfpow));
|
||||
b = 1;
|
||||
for (l = 0; l < 255; l++) {
|
||||
gfpow[l] = (unsigned char) b;
|
||||
gflog[b] = (unsigned char) l;
|
||||
b = b << 1;
|
||||
if (b & 256)
|
||||
b = b ^ 0x11d;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* This function printed the content of gflog[] and gfpow[] as C code
|
||||
and compared the content with the tables of the old implementation.
|
||||
h26[] and h45[] are reverted order copies of gfpow[]
|
||||
*/
|
||||
static int burn_rspc_print_tables(void)
|
||||
{
|
||||
int i;
|
||||
|
||||
printf("static unsigned char gfpow[255] = {");
|
||||
printf("\n\t");
|
||||
for(i= 0; i < 255; i++) {
|
||||
printf("%3u, ", gfpow[i]);
|
||||
|
||||
#ifdef Libburn_with_old_lec_comparisoN
|
||||
if(gfpow[i] != gf8_ilog[i])
|
||||
fprintf(stderr, "*** ILOG %d : %d != %d ***\n", i, gfpow[i], gf8_ilog[i]);
|
||||
#endif
|
||||
|
||||
if((i % 10) == 9)
|
||||
printf("\n\t");
|
||||
}
|
||||
printf("\n};\n\n");
|
||||
|
||||
printf("static unsigned char gflog[256] = {");
|
||||
printf("\n\t");
|
||||
for(i= 0; i < 256; i++) {
|
||||
printf(" %3u,", gflog[i]);
|
||||
|
||||
#ifdef Libburn_with_old_lec_comparisoN
|
||||
if(gflog[i] != gf8_log[i])
|
||||
fprintf(stderr, "*** LOG %d : %d != %d ***\n", i, gflog[i], gf8_log[i]);
|
||||
#endif
|
||||
|
||||
if((i % 10) == 9)
|
||||
printf("\n\t");
|
||||
}
|
||||
printf("\n};\n\n");
|
||||
|
||||
printf("static unsigned char h26[26] = {");
|
||||
printf("\n\t");
|
||||
for(i= 0; i < 26; i++) {
|
||||
printf(" %3u,", gfpow[25 - i]);
|
||||
if((i % 10) == 9)
|
||||
printf("\n\t");
|
||||
}
|
||||
printf("\n};\n\n");
|
||||
|
||||
printf("static unsigned char h45[45] = {");
|
||||
printf("\n\t");
|
||||
for(i= 0; i < 45; i++) {
|
||||
printf(" %3u,",gfpow[44 - i]);
|
||||
if((i % 10) == 9)
|
||||
printf("\n\t");
|
||||
}
|
||||
printf("\n};\n\n");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* This code was used to generate the content of array ecma_130_annex_b[].
|
||||
*/
|
||||
static unsigned short ecma_130_fsr = 1;
|
||||
|
||||
static int next_bit(void)
|
||||
{
|
||||
int ret;
|
||||
|
||||
ret = ecma_130_fsr & 1;
|
||||
ecma_130_fsr = (ecma_130_fsr >> 1) & 0x3fff;
|
||||
if (ret ^ (ecma_130_fsr & 1))
|
||||
ecma_130_fsr |= 0x4000;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int print_ecma_130_scrambler(void)
|
||||
{
|
||||
int i, j, b;
|
||||
|
||||
ecma_130_fsr = 1;
|
||||
printf("static unsigned char ecma_130_annex_b[2340] = {");
|
||||
printf("\n\t");
|
||||
for (i = 0; i < 2340; i++) {
|
||||
b = 0;
|
||||
for (j = 0; j < 8; j++)
|
||||
b |= next_bit() << j;
|
||||
|
||||
printf("%3u, ", b);
|
||||
if ((i % 10) == 9)
|
||||
printf("\n\t");
|
||||
}
|
||||
printf("\n};\n");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
#ifdef Libburn_with_general_rspc_diV
|
||||
|
||||
/* This is a general polynomial division function.
|
||||
burn_rspc_div_3() has been derived from this by setting b to constant 3.
|
||||
*/
|
||||
static unsigned char burn_rspc_div(unsigned char a, unsigned char b)
|
||||
{
|
||||
int d;
|
||||
|
||||
if (a == 0)
|
||||
return 0;
|
||||
if (b == 0)
|
||||
return -1;
|
||||
d = gflog[a] - gflog[b];
|
||||
if (d < 0)
|
||||
d += 255;
|
||||
return gfpow[d];
|
||||
}
|
||||
|
||||
#endif /* Libburn_with_general_rspc_diV */
|
||||
|
||||
|
||||
#endif /* Libburn_with_lec_generatoR */
|
||||
|
24
libburn/ecma130ab.h
Normal file
24
libburn/ecma130ab.h
Normal file
@ -0,0 +1,24 @@
|
||||
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
/* ts A91016 : libburn/ecma130ab.h is the replacement for old libburn/lec.h
|
||||
|
||||
Copyright 2009, Thomas Schmitt <scdbackup@gmx.net>, libburnia-project.org
|
||||
Provided under GPL version 2 or later.
|
||||
|
||||
This code module implements the computations prescribed in ECMA-130 Annex A
|
||||
and B. For explanations of the underlying mathematics see ecma130ab.c .
|
||||
|
||||
*/
|
||||
|
||||
#ifndef Libburn_ecma130ab_includeD
|
||||
#define Libburn_ecma130ab_includeD 1
|
||||
|
||||
void burn_rspc_parity_p(unsigned char *sector);
|
||||
|
||||
void burn_rspc_parity_q(unsigned char *sector);
|
||||
|
||||
void burn_ecma130_scramble(unsigned char *sector);
|
||||
|
||||
#endif /* ! Libburn_ecma130ab_includeD */
|
||||
|
855
libburn/file.c
855
libburn/file.c
@ -1,13 +1,35 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <sys/types.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <sys/stat.h>
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#include <time.h>
|
||||
#include <pthread.h>
|
||||
|
||||
#include "source.h"
|
||||
#include "libburn.h"
|
||||
#include "file.h"
|
||||
#include "async.h"
|
||||
|
||||
#include "libdax_msgs.h"
|
||||
extern struct libdax_msgs *libdax_messenger;
|
||||
|
||||
|
||||
/* main channel data can be padded on read, but 0 padding the subs will make
|
||||
an unreadable disc */
|
||||
@ -16,8 +38,6 @@ an unreadable disc */
|
||||
/* This is a generic OS oriented function wrapper which compensates
|
||||
shortcommings of read() in respect to a guaranteed amount of return data.
|
||||
See man 2 read , paragraph "RETURN VALUE".
|
||||
Possibly libburn/file.c is not the right storage location for this.
|
||||
To make it ready for a move, this function is not declared static.
|
||||
*/
|
||||
static int read_full_buffer(int fd, unsigned char *buffer, int size)
|
||||
{
|
||||
@ -42,7 +62,7 @@ static int file_read(struct burn_source *source,
|
||||
unsigned char *buffer,
|
||||
int size)
|
||||
{
|
||||
struct burn_source_fd *fs = source->data;
|
||||
struct burn_source_file *fs = source->data;
|
||||
|
||||
return read_full_buffer(fs->datafd, buffer, size);
|
||||
}
|
||||
@ -71,117 +91,820 @@ static off_t file_size(struct burn_source *source)
|
||||
struct stat buf;
|
||||
struct burn_source_file *fs = source->data;
|
||||
|
||||
if (fstat(fs->datafd, &buf) == -1)
|
||||
if (fs->fixed_size > 0)
|
||||
return fs->fixed_size;
|
||||
if (fstat(fs->datafd, &buf) != 0)
|
||||
return (off_t) 0;
|
||||
if ((buf.st_mode & S_IFMT) != S_IFREG)
|
||||
return (off_t) 0;
|
||||
/* for now we keep it compatible to the old (int) return value */
|
||||
if(buf.st_size >= 1308622848) /* 2 GB - 800 MB to prevent rollover */
|
||||
return (off_t) 1308622848;
|
||||
return (off_t) buf.st_size;
|
||||
}
|
||||
|
||||
|
||||
/* ts A70125 */
|
||||
static int file_set_size(struct burn_source *source, off_t size)
|
||||
{
|
||||
struct burn_source_file *fs = source->data;
|
||||
|
||||
fs->fixed_size = size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
struct burn_source *burn_file_source_new(const char *path, const char *subpath)
|
||||
{
|
||||
struct burn_source_file *fs;
|
||||
struct burn_source *src;
|
||||
int fd1, fd2 = 0;
|
||||
int fd1 = -1, fd2 = -1;
|
||||
|
||||
if (!path)
|
||||
return NULL;
|
||||
fd1 = open(path, O_RDONLY);
|
||||
if (fd1 == -1)
|
||||
return NULL;
|
||||
if (subpath) {
|
||||
if (subpath != NULL) {
|
||||
fd2 = open(subpath, O_RDONLY);
|
||||
if (fd2 == -1) {
|
||||
close(fd1);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
fs = malloc(sizeof(struct burn_source_file));
|
||||
fs->datafd = fd1;
|
||||
fs = calloc(1, sizeof(struct burn_source_file));
|
||||
|
||||
if (subpath)
|
||||
fs->subfd = fd2;
|
||||
/* ts A70825 */
|
||||
if (fs == NULL) {
|
||||
failure:;
|
||||
close(fd1);
|
||||
if (fd2 >= 0)
|
||||
close(fd2);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
fs->datafd = fd1;
|
||||
fs->subfd = fd2;
|
||||
|
||||
/* ts A70125 */
|
||||
fs->fixed_size = 0;
|
||||
|
||||
src = burn_source_new();
|
||||
|
||||
/* ts A70825 */
|
||||
if (src == NULL) {
|
||||
free((char *) fs);
|
||||
goto failure;
|
||||
}
|
||||
|
||||
src->read = file_read;
|
||||
if (subpath)
|
||||
src->read_sub = file_read_sub;
|
||||
|
||||
src->get_size = file_size;
|
||||
src->set_size = file_set_size;
|
||||
src->free_data = file_free;
|
||||
src->data = fs;
|
||||
return src;
|
||||
}
|
||||
|
||||
|
||||
/* ------ provisory location for the new source subclass fd --------- */
|
||||
|
||||
static off_t fd_get_size(struct burn_source *source)
|
||||
{
|
||||
struct stat buf;
|
||||
struct burn_source_fd *fs = source->data;
|
||||
|
||||
if (fs->fixed_size > 0)
|
||||
return fs->fixed_size;
|
||||
if (fstat(fs->datafd, &buf) == -1)
|
||||
return (off_t) 0;
|
||||
/* for now we keep it compatible to the old (int) return value */
|
||||
if (buf.st_size >= 1308622848) /* 2 GB - 800 MB to prevent rollover */
|
||||
return (off_t) 1308622848;
|
||||
return buf.st_size;
|
||||
}
|
||||
|
||||
static int fd_read(struct burn_source *source,
|
||||
unsigned char *buffer,
|
||||
int size)
|
||||
{
|
||||
struct burn_source_fd *fs = source->data;
|
||||
|
||||
return read_full_buffer(fs->datafd, buffer, size);
|
||||
}
|
||||
|
||||
|
||||
static int fd_read_sub(struct burn_source *source,
|
||||
unsigned char *buffer,
|
||||
int size)
|
||||
{
|
||||
struct burn_source_fd *fs = source->data;
|
||||
|
||||
return read_full_buffer(fs->subfd, buffer, size);
|
||||
}
|
||||
|
||||
|
||||
static void fd_free_data(struct burn_source *source)
|
||||
{
|
||||
struct burn_source_fd *fs = source->data;
|
||||
|
||||
close(fs->datafd);
|
||||
if (source->read_sub)
|
||||
close(fs->subfd);
|
||||
free(fs);
|
||||
}
|
||||
|
||||
/* ts A70126 : removed class burn_source_fd in favor of burn_source_file */
|
||||
|
||||
struct burn_source *burn_fd_source_new(int datafd, int subfd, off_t size)
|
||||
{
|
||||
struct burn_source_fd *fs;
|
||||
struct burn_source_file *fs;
|
||||
struct burn_source *src;
|
||||
|
||||
if (datafd == -1)
|
||||
return NULL;
|
||||
fs = malloc(sizeof(struct burn_source_fd));
|
||||
fs = calloc(1, sizeof(struct burn_source_file));
|
||||
if (fs == NULL) /* ts A70825 */
|
||||
return NULL;
|
||||
fs->datafd = datafd;
|
||||
fs->subfd = subfd;
|
||||
fs->fixed_size = size;
|
||||
|
||||
src = burn_source_new();
|
||||
src->read = fd_read;
|
||||
|
||||
/* ts A70825 */
|
||||
if (src == NULL) {
|
||||
free((char *) fs);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
src->read = file_read;
|
||||
if(subfd != -1)
|
||||
src->read = fd_read_sub;
|
||||
src->get_size = fd_get_size;
|
||||
src->free_data = fd_free_data;
|
||||
src->read_sub = file_read_sub;
|
||||
src->get_size = file_size;
|
||||
src->set_size = file_set_size;
|
||||
src->free_data = file_free;
|
||||
src->data = fs;
|
||||
return src;
|
||||
}
|
||||
|
||||
|
||||
/* ts A71003 */
|
||||
/* ------------------------------ fifo --------------------------- */
|
||||
|
||||
/* The fifo mechanism consists of a burn_source proxy which is here,
|
||||
a thread management team which is located in async.c,
|
||||
and a synchronous shoveller which is here.
|
||||
*/
|
||||
|
||||
static int fifo_sleep(int flag)
|
||||
{
|
||||
static unsigned long sleeptime = 50000; /* 50 ms */
|
||||
|
||||
usleep(sleeptime);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
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, counted = 0;
|
||||
|
||||
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;
|
||||
}
|
||||
if (!counted)
|
||||
fs->empty_counter++;
|
||||
counted = 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);
|
||||
*/
|
||||
|
||||
fs->get_counter++;
|
||||
return (size - todo);
|
||||
}
|
||||
|
||||
|
||||
static off_t fifo_get_size(struct burn_source *source)
|
||||
{
|
||||
struct burn_source_fifo *fs = source->data;
|
||||
|
||||
return fs->inp->get_size(fs->inp);
|
||||
}
|
||||
|
||||
|
||||
static int fifo_set_size(struct burn_source *source, off_t size)
|
||||
{
|
||||
struct burn_source_fifo *fs = source->data;
|
||||
|
||||
return fs->inp->set_size(fs->inp, size);
|
||||
}
|
||||
|
||||
|
||||
static void fifo_free(struct burn_source *source)
|
||||
{
|
||||
struct burn_source_fifo *fs = source->data;
|
||||
|
||||
burn_fifo_abort(fs, 0);
|
||||
if (fs->inp != NULL)
|
||||
burn_source_free(fs->inp);
|
||||
|
||||
if (fs->buf != NULL)
|
||||
burn_os_free_buffer(fs->buf,
|
||||
((size_t) fs->chunksize) * (size_t) fs->chunks, 0);
|
||||
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, fill;
|
||||
int counted;
|
||||
char *bufpt;
|
||||
pthread_t thread_handle_storage;
|
||||
|
||||
fs->thread_handle= &thread_handle_storage;
|
||||
*((pthread_t *) fs->thread_handle)= pthread_self();
|
||||
fs->thread_pid = getpid();
|
||||
fs->thread_is_valid = 1;
|
||||
|
||||
bufsize = fs->chunksize * fs->chunks;
|
||||
while (!fs->end_of_consumption) {
|
||||
|
||||
/* wait for enough buffer space available */
|
||||
wpos = fs->buf_writepos;
|
||||
counted = 0;
|
||||
while (1) {
|
||||
rpos = fs->buf_readpos;
|
||||
diff = rpos - wpos;
|
||||
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->inp_read_size)
|
||||
trans_end = 1;
|
||||
}
|
||||
if (free_bytes >= fs->inp_read_size)
|
||||
break;
|
||||
if (!counted)
|
||||
fs->full_counter++;
|
||||
counted = 1;
|
||||
fifo_sleep(0);
|
||||
}
|
||||
|
||||
fill = bufsize - free_bytes - 1;
|
||||
if (fill < fs->total_min_fill)
|
||||
fs->total_min_fill = fill;
|
||||
if (fill < fs->interval_min_fill)
|
||||
fs->interval_min_fill = fill;
|
||||
|
||||
/* prepare the receiving memory */
|
||||
bufpt = fs->buf + wpos;
|
||||
if (trans_end) {
|
||||
bufpt = burn_os_alloc_buffer(
|
||||
(size_t) fs->inp_read_size, 0);
|
||||
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->inp_read_size);
|
||||
else
|
||||
ret = fs->inp->read_xt( fs->inp,
|
||||
(unsigned char *) bufpt, fs->inp_read_size);
|
||||
if (ret == 0) {
|
||||
|
||||
/* >>> ??? ts B00326 */
|
||||
/* >>> report EOF of fifo input and fs->in_counter */;
|
||||
|
||||
break; /* EOF */
|
||||
} else if (ret < 0) {
|
||||
libdax_msgs_submit(libdax_messenger, -1, 0x00020153,
|
||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Read error on fifo input", errno, 0);
|
||||
fs->input_error = errno;
|
||||
if(errno == 0)
|
||||
fs->input_error = EIO;
|
||||
break;
|
||||
}
|
||||
fs->in_counter += ret;
|
||||
fs->put_counter++;
|
||||
|
||||
/* activate read chunk */
|
||||
if (ret > fs->inp_read_size)
|
||||
/* beware of ill custom burn_source */
|
||||
ret = fs->inp_read_size;
|
||||
if (trans_end) {
|
||||
/* copy to end of buffer */
|
||||
memcpy(fs->buf + wpos, bufpt, bufsize - wpos);
|
||||
/* copy to start of buffer */
|
||||
memcpy(fs->buf, bufpt + (bufsize - wpos),
|
||||
fs->inp_read_size - (bufsize - wpos));
|
||||
burn_os_free_buffer(bufpt, (size_t) fs->inp_read_size,
|
||||
0);
|
||||
if (ret >= bufsize - wpos)
|
||||
fs->buf_writepos = ret - (bufsize - wpos);
|
||||
else
|
||||
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.
|
||||
*/
|
||||
if(fs->buf != NULL)
|
||||
burn_os_free_buffer(fs->buf,
|
||||
((size_t) fs->chunksize) * (size_t) fs->chunks, 0);
|
||||
fs->buf = NULL;
|
||||
|
||||
fs->thread_handle= NULL;
|
||||
fs->thread_is_valid = 0;
|
||||
return (fs->input_error == 0);
|
||||
}
|
||||
|
||||
|
||||
int burn_fifo_cancel(struct burn_source *source)
|
||||
{
|
||||
int ret;
|
||||
struct burn_source_fifo *fs = source->data;
|
||||
|
||||
ret = burn_source_cancel(fs->inp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
@param flag bit0= allow larger read chunks
|
||||
*/
|
||||
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 = calloc(1, sizeof(struct burn_source_fifo));
|
||||
if (fs == NULL)
|
||||
return NULL;
|
||||
fs->is_started = 0;
|
||||
fs->thread_handle = NULL;
|
||||
fs->thread_pid = 0;
|
||||
fs->thread_is_valid = 0;
|
||||
fs->inp = NULL; /* set later */
|
||||
if (flag & 1)
|
||||
fs->inp_read_size = 32 * 1024;
|
||||
else
|
||||
fs->inp_read_size = chunksize;
|
||||
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;
|
||||
fs->total_min_fill = fs->interval_min_fill = 0;
|
||||
fs->put_counter = fs->get_counter = 0;
|
||||
fs->empty_counter = fs->full_counter = 0;
|
||||
|
||||
src = burn_source_new();
|
||||
if (src == NULL) {
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/* ts A91125 : API */
|
||||
void burn_fifo_get_statistics(struct burn_source *source,
|
||||
int *total_min_fill, int *interval_min_fill,
|
||||
int *put_counter, int *get_counter,
|
||||
int *empty_counter, int *full_counter)
|
||||
{
|
||||
struct burn_source_fifo *fs = source->data;
|
||||
|
||||
*total_min_fill = fs->total_min_fill;
|
||||
*interval_min_fill = fs->interval_min_fill;
|
||||
*put_counter = fs->put_counter;
|
||||
*get_counter = fs->get_counter;
|
||||
*empty_counter = fs->empty_counter;
|
||||
*full_counter = fs->full_counter;
|
||||
}
|
||||
|
||||
|
||||
/* ts A91125 : API */
|
||||
void burn_fifo_next_interval(struct burn_source *source,
|
||||
int *interval_min_fill)
|
||||
{
|
||||
struct burn_source_fifo *fs = source->data;
|
||||
int size, free_bytes, ret;
|
||||
char *status_text;
|
||||
|
||||
*interval_min_fill = fs->interval_min_fill;
|
||||
ret = burn_fifo_inquire_status(source,
|
||||
&size, &free_bytes, &status_text);
|
||||
fs->interval_min_fill = size - free_bytes - 1;
|
||||
}
|
||||
|
||||
|
||||
/* @param flag bit0= do not copy to buf but only wait until the fifo has read
|
||||
bufsize or input ended.
|
||||
The same happens if buf is NULL.
|
||||
bit1= fill to max fifo size
|
||||
*/
|
||||
int burn_fifo_fill_data(struct burn_source *source, char *buf, int bufsize,
|
||||
int flag)
|
||||
{
|
||||
int size, free_bytes, ret, wait_count= 0;
|
||||
char *status_text;
|
||||
struct burn_source_fifo *fs = source->data;
|
||||
|
||||
if (buf == NULL)
|
||||
flag |= 1;
|
||||
|
||||
/* Eventually start fifo thread by reading 0 bytes */
|
||||
ret = fifo_read(source, (unsigned char *) NULL, 0);
|
||||
if (ret<0)
|
||||
{ret = 0; goto ex;}
|
||||
|
||||
/* wait for at least bufsize bytes being ready */
|
||||
while (1) {
|
||||
ret= burn_fifo_inquire_status(source,
|
||||
&size, &free_bytes, &status_text);
|
||||
if (flag & 2) {
|
||||
bufsize = size - (size % fs->inp_read_size) -
|
||||
fs->inp_read_size;
|
||||
if (bufsize <= 0)
|
||||
{ret = 0; goto ex;}
|
||||
}
|
||||
if (size - fs->inp_read_size < bufsize) {
|
||||
if (flag & 1) {
|
||||
bufsize = size - (size % fs->inp_read_size) -
|
||||
fs->inp_read_size;
|
||||
if (bufsize <= 0)
|
||||
{ret = 0; goto ex;}
|
||||
} else {
|
||||
libdax_msgs_submit(libdax_messenger, -1,
|
||||
0x0002015c, LIBDAX_MSGS_SEV_FAILURE,
|
||||
LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Fifo size too small for desired peek buffer",
|
||||
0, 0);
|
||||
{ret = -1; goto ex;}
|
||||
}
|
||||
}
|
||||
if (fs->out_counter > 0 || (ret & 4) || fs->buf == NULL) {
|
||||
libdax_msgs_submit(libdax_messenger, -1, 0x0002015e,
|
||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Fifo is already under consumption when peeking is desired",
|
||||
0, 0);
|
||||
{ret = -1; goto ex;}
|
||||
}
|
||||
if(size - free_bytes >= bufsize) {
|
||||
|
||||
/* <<<
|
||||
fprintf(stderr,
|
||||
"libburn_DEBUG: after waiting cycle %d : fifo %s , %d bytes\n",
|
||||
wait_count, status_text, size - free_bytes);
|
||||
*/
|
||||
if(!(flag & 1))
|
||||
memcpy(buf, fs->buf, bufsize);
|
||||
{ret = 1; goto ex;}
|
||||
}
|
||||
|
||||
if (ret & 2) {
|
||||
/* input has ended, not enough data arrived */
|
||||
if (flag & 1)
|
||||
{ret = 0; goto ex;}
|
||||
libdax_msgs_submit(libdax_messenger, -1, 0x0002015d,
|
||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Fifo input ended short of desired peek buffer size",
|
||||
0, 0);
|
||||
{ret = 0; goto ex;}
|
||||
}
|
||||
|
||||
if (free_bytes < fs->inp_read_size) {
|
||||
/* Usable fifo size filled, not enough data arrived */
|
||||
if (flag & 1)
|
||||
{ret = 0; goto ex;}
|
||||
libdax_msgs_submit(libdax_messenger, -1, 0x00020174,
|
||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Fifo alignment does not allow desired read size",
|
||||
0, 0);
|
||||
{ret = 0; goto ex;}
|
||||
}
|
||||
|
||||
usleep(100000);
|
||||
wait_count++;
|
||||
|
||||
/* <<<
|
||||
if(wait_count%10==0)
|
||||
fprintf(stderr,
|
||||
"libburn_DEBUG: waiting cycle %d : fifo %s , %d bytes\n",
|
||||
wait_count, status_text, size - free_bytes);
|
||||
*/
|
||||
|
||||
}
|
||||
ret = 0;
|
||||
ex:;
|
||||
fs->total_min_fill = fs->interval_min_fill = fs->buf_writepos;
|
||||
return(ret);
|
||||
}
|
||||
|
||||
|
||||
/* ts A80713 : API */
|
||||
int burn_fifo_peek_data(struct burn_source *source, char *buf, int bufsize,
|
||||
int flag)
|
||||
{
|
||||
return burn_fifo_fill_data(source, buf, bufsize, 0);
|
||||
}
|
||||
|
||||
|
||||
/* ts A91125 : API */
|
||||
int burn_fifo_fill(struct burn_source *source, int bufsize, int flag)
|
||||
{
|
||||
return burn_fifo_fill_data(source, NULL, bufsize,
|
||||
1 | ((flag & 1) << 1));
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------- Offset source ----------------------------- */
|
||||
/* ts B00922 */
|
||||
|
||||
static void offst_free(struct burn_source *source);
|
||||
|
||||
static struct burn_source_offst *offst_auth(struct burn_source *source)
|
||||
{
|
||||
if (source->free_data != offst_free) {
|
||||
libdax_msgs_submit(libdax_messenger, -1, 0x0002017a,
|
||||
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Expected offset source object as parameter",
|
||||
0, 0);
|
||||
return NULL;
|
||||
}
|
||||
return (struct burn_source_offst *) source->data;
|
||||
}
|
||||
|
||||
static off_t offst_get_size(struct burn_source *source)
|
||||
{
|
||||
struct burn_source_offst *fs;
|
||||
|
||||
if ((fs = offst_auth(source)) == NULL)
|
||||
return (off_t) 0;
|
||||
return fs->size;
|
||||
}
|
||||
|
||||
static int offst_set_size(struct burn_source *source, off_t size)
|
||||
{
|
||||
struct burn_source_offst *fs;
|
||||
|
||||
if ((fs = offst_auth(source)) == NULL)
|
||||
return 0;
|
||||
fs->size = size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
static void offst_free(struct burn_source *source)
|
||||
{
|
||||
struct burn_source_offst *fs;
|
||||
|
||||
if ((fs = offst_auth(source)) == NULL)
|
||||
return;
|
||||
if (fs->prev != NULL)
|
||||
offst_auth(fs->prev)->next = fs->next;
|
||||
if (fs->next != NULL)
|
||||
offst_auth(fs->next)->prev = fs->prev;
|
||||
if (fs->inp != NULL)
|
||||
burn_source_free(fs->inp); /* i.e. decrement refcount */
|
||||
free(source->data);
|
||||
}
|
||||
|
||||
static int offst_read(struct burn_source *source, unsigned char *buffer,
|
||||
int size)
|
||||
{
|
||||
int ret, to_read, todo;
|
||||
struct burn_source_offst *fs;
|
||||
|
||||
if ((fs = offst_auth(source)) == NULL)
|
||||
return -1;
|
||||
|
||||
/* Eventually skip bytes up to start position */;
|
||||
if (!fs->running) {
|
||||
if (fs->prev != NULL)
|
||||
fs->pos = offst_auth(fs->prev)->pos;
|
||||
fs->running= 1;
|
||||
}
|
||||
if(fs->pos < fs->start) {
|
||||
todo = fs->start - fs->pos;
|
||||
while (todo > 0) {
|
||||
to_read = todo;
|
||||
if (to_read > size)
|
||||
to_read = size;
|
||||
ret = burn_source_read(fs->inp, buffer, to_read);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
todo -= ret;
|
||||
fs->pos += ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Produce EOF if source size is exhausted.
|
||||
burn_source delivers no incomplete sector buffers.
|
||||
*/
|
||||
if (fs->pos + size > fs->start + fs->size)
|
||||
return 0;
|
||||
|
||||
/* Read payload */
|
||||
ret = burn_source_read(fs->inp, buffer, size);
|
||||
if (ret > 0)
|
||||
fs->pos += ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int offst_cancel(struct burn_source *source)
|
||||
{
|
||||
int ret;
|
||||
struct burn_source_offst *fs;
|
||||
|
||||
if ((fs = offst_auth(source)) == NULL)
|
||||
return -1;
|
||||
ret = burn_source_cancel(fs->inp);
|
||||
return ret;
|
||||
}
|
||||
|
||||
struct burn_source *burn_offst_source_new(
|
||||
struct burn_source *inp, struct burn_source *prev,
|
||||
off_t start, off_t size, int flag)
|
||||
{
|
||||
struct burn_source *src;
|
||||
struct burn_source_offst *fs, *prev_fs = NULL;
|
||||
|
||||
if (prev != NULL)
|
||||
if ((prev_fs = offst_auth(prev)) == NULL)
|
||||
return NULL; /* Not type burn_source_offst */
|
||||
|
||||
fs = calloc(1, sizeof(struct burn_source_offst));
|
||||
if (fs == NULL)
|
||||
return NULL;
|
||||
src = burn_source_new();
|
||||
if (src == NULL) {
|
||||
free((char *) fs);
|
||||
return NULL;
|
||||
}
|
||||
src->read = NULL;
|
||||
src->read_sub = NULL;
|
||||
src->get_size = offst_get_size;
|
||||
src->set_size = offst_set_size;
|
||||
src->free_data = offst_free;
|
||||
src->data = fs;
|
||||
src->version= 1;
|
||||
src->read_xt = offst_read;
|
||||
src->cancel= offst_cancel;
|
||||
fs->inp = inp;
|
||||
fs->prev = prev;
|
||||
fs->next = NULL;
|
||||
if (prev != NULL) {
|
||||
if (prev_fs->next != NULL) {
|
||||
offst_auth(prev_fs->next)->prev = src;
|
||||
fs->next = prev_fs->next;
|
||||
}
|
||||
prev_fs->next = src;
|
||||
if (prev_fs->start + prev_fs->size > start) {
|
||||
libdax_msgs_submit(libdax_messenger, -1, 0x00020179,
|
||||
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Offset source start address is before end of previous source",
|
||||
0, 0);
|
||||
return NULL;
|
||||
}
|
||||
}
|
||||
fs->start = start;
|
||||
fs->size = size;
|
||||
fs->running = 0;
|
||||
fs->pos = 0;
|
||||
inp->refcount++; /* make sure inp lives longer than src */
|
||||
|
||||
return src;
|
||||
}
|
||||
|
||||
|
@ -1,22 +1,95 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
#ifndef BURN__FILE_H
|
||||
#define BURN__FILE_H
|
||||
|
||||
struct burn_source_file
|
||||
{
|
||||
int datafd;
|
||||
int subfd;
|
||||
};
|
||||
char magic[4];
|
||||
|
||||
|
||||
/* ------ provisory location for the new source subclass fd --------- */
|
||||
|
||||
struct burn_source_fd
|
||||
{
|
||||
int datafd;
|
||||
int subfd;
|
||||
off_t fixed_size;
|
||||
};
|
||||
|
||||
/* ts A70126 : burn_source_file obsoleted burn_source_fd */
|
||||
|
||||
|
||||
/* ts A70930 */
|
||||
struct burn_source_fifo {
|
||||
char magic[4];
|
||||
|
||||
/* The fifo stays inactive and unequipped with eventual resources
|
||||
until its read() method is called for the first time.
|
||||
Only then burn_fifo_start() gets called, allocates the complete
|
||||
resources, starts a thread with burn_fifo_source_shuffler()
|
||||
which shuffles data and finally destroys the resources.
|
||||
This late start is to stay modest in case of multiple tracks
|
||||
in one disc.
|
||||
*/
|
||||
int is_started;
|
||||
|
||||
void *thread_handle; /* actually a pointer to a thread_t */
|
||||
int thread_pid;
|
||||
int thread_is_valid;
|
||||
|
||||
/* the burn_source for which this fifo is acting as proxy */
|
||||
struct burn_source *inp;
|
||||
int inp_read_size;
|
||||
|
||||
/* <<< 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;
|
||||
|
||||
int total_min_fill;
|
||||
int interval_min_fill;
|
||||
int put_counter;
|
||||
int get_counter;
|
||||
int empty_counter;
|
||||
int full_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);
|
||||
|
||||
|
||||
/* ts B00922 */
|
||||
struct burn_source_offst {
|
||||
|
||||
/* See burn_offst_source_new() */
|
||||
struct burn_source *inp;
|
||||
struct burn_source *prev;
|
||||
off_t start;
|
||||
off_t size;
|
||||
|
||||
/* To help offst_free() */
|
||||
struct burn_source *next;
|
||||
|
||||
/* The current reading position */
|
||||
int running;
|
||||
off_t pos;
|
||||
|
||||
};
|
||||
|
||||
#endif /* LIBBURN__FILE_H */
|
||||
|
385
libburn/init.c
385
libburn/init.c
@ -1,5 +1,15 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||
Copyright (c) 2006 - 2011 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
|
||||
/* ts A61007 */
|
||||
@ -8,12 +18,19 @@
|
||||
#include <stdio.h>
|
||||
#include <signal.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <pthread.h>
|
||||
|
||||
/* ts A70928 : init.h is for others, not for init .c
|
||||
#include "init.h"
|
||||
*/
|
||||
|
||||
|
||||
#include "sg.h"
|
||||
#include "error.h"
|
||||
#include "libburn.h"
|
||||
#include "drive.h"
|
||||
#include "transport.h"
|
||||
|
||||
/* ts A60825 : The storage location for back_hacks.h variables. */
|
||||
#define BURN_BACK_HACKS_INIT 1
|
||||
@ -26,9 +43,24 @@ struct libdax_msgs *libdax_messenger= NULL;
|
||||
|
||||
int burn_running = 0;
|
||||
|
||||
/* ts A60813 : wether to use O_EXCL and/or O_NONBLOCK in libburn/sg.c */
|
||||
/* ts A60813 : GNU/Linux: whether to use O_EXCL on open() of device files
|
||||
ts B00212 : FreeBSD: whether to use flock(LOCK_EX) after open()
|
||||
*/
|
||||
int burn_sg_open_o_excl = 1;
|
||||
|
||||
/* ts A70403 : GNU/Linux: wether to use fcntl(,F_SETLK,)
|
||||
after open() of device files */
|
||||
int burn_sg_fcntl_f_setlk = 1;
|
||||
|
||||
/* ts A70314 : GNU/Linux: what device family to use :
|
||||
0= default family
|
||||
1= sr
|
||||
2= scd
|
||||
(3= st)
|
||||
4= sg
|
||||
*/
|
||||
int burn_sg_use_family = 0;
|
||||
|
||||
/* O_NONBLOCK was hardcoded in enumerate_ata() which i hardly use.
|
||||
For enumerate_sg() it seems ok.
|
||||
So it should stay default mode until enumerate_ata() without O_NONBLOCK
|
||||
@ -41,6 +73,11 @@ int burn_sg_open_o_nonblock = 1;
|
||||
int burn_sg_open_abort_busy = 0;
|
||||
|
||||
|
||||
/* The message returned from sg_id_string() and/or sg_initialize()
|
||||
*/
|
||||
static char sg_initialize_msg[1024] = {""};
|
||||
|
||||
|
||||
/* ts A61002 */
|
||||
|
||||
#include "cleanup.h"
|
||||
@ -48,6 +85,32 @@ int burn_sg_open_abort_busy = 0;
|
||||
/* Parameters for builtin abort handler */
|
||||
static char abort_message_prefix[81] = {"libburn : "};
|
||||
static pid_t abort_control_pid= 0;
|
||||
static pthread_t abort_control_thread;
|
||||
volatile int burn_global_abort_level= 0;
|
||||
int burn_global_abort_signum= 0;
|
||||
void *burn_global_signal_handle = NULL;
|
||||
burn_abort_handler_t burn_global_signal_handler = NULL;
|
||||
int burn_builtin_signal_action = 0; /* burn_set_signal_handling() */
|
||||
volatile int burn_builtin_triggered_action = 0; /* burn_is_aborting() */
|
||||
|
||||
|
||||
/* ts A70223 : wether implemented untested profiles are supported */
|
||||
int burn_support_untested_profiles = 0;
|
||||
|
||||
/* ts A91111 :
|
||||
whether to log SCSI commands (to be implemented in sg-*.c)
|
||||
bit0= log in /tmp/libburn_sg_command_log
|
||||
bit1= log to stderr
|
||||
bit2= flush every line
|
||||
*/
|
||||
int burn_sg_log_scsi = 0;
|
||||
|
||||
|
||||
/* ts B10312 :
|
||||
Whether to map random-access readonly files to drive role 4.
|
||||
Else it is role 2 overwriteable drive
|
||||
*/
|
||||
int burn_drive_role_4_allowed = 0;
|
||||
|
||||
|
||||
/* ts A60925 : ticket 74 */
|
||||
@ -73,9 +136,18 @@ int burn_initialize(void)
|
||||
|
||||
if (burn_running)
|
||||
return 1;
|
||||
burn_support_untested_profiles = 0;
|
||||
ret = burn_msgs_initialize();
|
||||
if (ret <= 0)
|
||||
return 0;
|
||||
ret = sg_initialize(sg_initialize_msg, 0);
|
||||
if (ret <= 0) {
|
||||
libdax_msgs_submit(libdax_messenger, -1,
|
||||
0x00020175,
|
||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
||||
sg_initialize_msg, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
burn_running = 1;
|
||||
return 1;
|
||||
}
|
||||
@ -89,11 +161,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" */
|
||||
@ -102,10 +175,24 @@ void burn_finish(void)
|
||||
/* ts A60924 : ticket 74 */
|
||||
libdax_msgs_destroy(&libdax_messenger,0);
|
||||
|
||||
sg_shutdown(0);
|
||||
|
||||
burn_drive_clear_whitelist();
|
||||
|
||||
burn_running = 0;
|
||||
}
|
||||
|
||||
|
||||
/* ts A91226 */
|
||||
/** API function. See libburn.h */
|
||||
char *burn_scsi_transport_id(int flag)
|
||||
{
|
||||
if (!burn_running)
|
||||
sg_id_string(sg_initialize_msg, 0);
|
||||
return sg_initialize_msg;
|
||||
}
|
||||
|
||||
|
||||
/* ts A60813 */
|
||||
/** API function. See libburn.h */
|
||||
void burn_preset_device_open(int exclusive, int blocking, int abort_on_busy)
|
||||
@ -114,10 +201,11 @@ void burn_preset_device_open(int exclusive, int blocking, int abort_on_busy)
|
||||
/* a ssert(burn_running); */
|
||||
if (!burn_running)
|
||||
return;
|
||||
|
||||
burn_sg_open_o_excl= exclusive;
|
||||
burn_sg_open_o_nonblock= !blocking;
|
||||
burn_sg_open_abort_busy= !!abort_on_busy;
|
||||
burn_sg_open_o_excl = exclusive & 3;
|
||||
burn_sg_fcntl_f_setlk = !!(exclusive & 32);
|
||||
burn_sg_use_family = (exclusive >> 2) & 7;
|
||||
burn_sg_open_o_nonblock = !blocking;
|
||||
burn_sg_open_abort_busy = !!abort_on_busy;
|
||||
}
|
||||
|
||||
|
||||
@ -181,6 +269,8 @@ int burn_msgs_obtain(char *minimum_severity,
|
||||
ret = libdax_msgs__text_to_sev(minimum_severity, &minimum_sevno, 0);
|
||||
if (ret <= 0)
|
||||
return 0;
|
||||
if (libdax_messenger == NULL)
|
||||
return 0;
|
||||
ret = libdax_msgs_obtain(libdax_messenger, &item, minimum_sevno,
|
||||
LIBDAX_MSGS_PRIO_ZERO, 0);
|
||||
if (ret <= 0)
|
||||
@ -207,11 +297,179 @@ 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;
|
||||
}
|
||||
|
||||
/* ts B00224 */
|
||||
char *burn_util_thread_id(pid_t pid, pthread_t tid, char text[80])
|
||||
{
|
||||
int i, l;
|
||||
|
||||
sprintf(text, "[%lu,", (unsigned long int) getpid());
|
||||
l= strlen(text);
|
||||
for(i= 0; i < ((int) sizeof(pthread_t)) && 2 * i < 80 - l - 3; i++)
|
||||
sprintf(text + l + 2 * i,
|
||||
"%2.2X", ((unsigned char *) &tid)[i]);
|
||||
|
||||
sprintf(text + l + 2 * i, "]");
|
||||
return text;
|
||||
}
|
||||
|
||||
int burn_builtin_abort_handler(void *handle, int signum, int flag)
|
||||
{
|
||||
if(getpid() != abort_control_pid)
|
||||
|
||||
#define Libburn_new_thread_signal_handleR 1
|
||||
/*
|
||||
#define Libburn_signal_handler_verbouS 1
|
||||
*/
|
||||
|
||||
int ret;
|
||||
struct burn_drive *d;
|
||||
|
||||
#ifdef Libburn_signal_handler_verbouS
|
||||
char text[80];
|
||||
|
||||
fprintf(stderr, "libburn_ABORT: in = %s\n",
|
||||
burn_util_thread_id(getpid(), pthread_self(), text));
|
||||
fprintf(stderr, "libburn_ABORT: ctrl = %s\n",
|
||||
burn_util_thread_id(abort_control_pid, abort_control_thread,
|
||||
text));
|
||||
if (burn_global_signal_handler == burn_builtin_abort_handler)
|
||||
fprintf(stderr, "libburn_ABORT: signal action = %d\n",
|
||||
burn_builtin_signal_action);
|
||||
|
||||
/* >>> find writing drives and report their tid
|
||||
fprintf(stderr, "libburn_ABORT: wrt = %s\n",
|
||||
burn_util_thread_id(0, burn_write_thread_id, text));
|
||||
fprintf(stderr, "libburn_ABORT: sig= %d\n", signum);
|
||||
*/
|
||||
#endif
|
||||
|
||||
burn_builtin_triggered_action = burn_builtin_signal_action;
|
||||
burn_global_abort_level = -1;
|
||||
|
||||
if (burn_builtin_signal_action > 1) {
|
||||
Cleanup_set_handlers(NULL, NULL, 2);
|
||||
if (burn_builtin_signal_action == 4)
|
||||
return -2;
|
||||
fprintf(stderr,"%sABORT : Trying to shut down busy drives\n",
|
||||
abort_message_prefix);
|
||||
fprintf(stderr,
|
||||
"%sABORT : Wait the normal burning time before any kill -9\n",
|
||||
abort_message_prefix);
|
||||
burn_abort_5(0, burn_abort_pacifier, abort_message_prefix,
|
||||
0, 1);
|
||||
libdax_msgs_submit(libdax_messenger, -1, 0x00020177,
|
||||
LIBDAX_MSGS_SEV_ABORT, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Urged drive worker threads to do emergency halt",
|
||||
0, 0);
|
||||
return -2;
|
||||
}
|
||||
|
||||
|
||||
/* ---- old deprecated stuck-in-abort-handler loop ---- */
|
||||
|
||||
/* ts A70928:
|
||||
Must be quick. Allowed to coincide with other thread and to share
|
||||
the increment with that one. It must not decrease, though, and
|
||||
yield at least 1 if any thread calls this function.
|
||||
*/
|
||||
burn_global_abort_level++;
|
||||
burn_global_abort_signum= signum;
|
||||
|
||||
if(getpid() != abort_control_pid) {
|
||||
|
||||
#ifdef Libburn_new_thread_signal_handleR
|
||||
|
||||
ret = burn_drive_find_by_thread_pid(&d, getpid(),
|
||||
pthread_self());
|
||||
if (ret > 0 && d->busy == BURN_DRIVE_WRITING) {
|
||||
/* This is an active writer thread */
|
||||
|
||||
#ifdef Libburn_signal_handler_verbouS
|
||||
fprintf(stderr, "libburn_ABORT: pid %d found drive busy with writing, (level= %d)\n", (int) getpid(), burn_global_abort_level);
|
||||
#endif
|
||||
|
||||
d->sync_cache(d);
|
||||
|
||||
/* >>> perform a more qualified end of burn process */;
|
||||
|
||||
d->busy = BURN_DRIVE_IDLE;
|
||||
|
||||
if (burn_global_abort_level > 0) {
|
||||
/* control process did not show up yet */
|
||||
#ifdef Libburn_signal_handler_verbouS
|
||||
fprintf(stderr, "libburn_ABORT: pid %d sending signum %d to pid %d\n", (int) getpid(), (int) signum, (int) abort_control_pid);
|
||||
#endif
|
||||
kill(abort_control_pid, signum);
|
||||
}
|
||||
|
||||
#ifdef Libburn_signal_handler_verbouS
|
||||
fprintf(stderr, "libburn_ABORT: pid %d signum %d returning -2\n", (int) getpid(), (int) signum);
|
||||
#endif
|
||||
|
||||
return -2;
|
||||
} else {
|
||||
usleep(1000000); /* calm down */
|
||||
return -2;
|
||||
}
|
||||
|
||||
#else
|
||||
usleep(1000000); /* calm down */
|
||||
return -2;
|
||||
#endif /* ! Libburn_new_thread_signal_handleR */
|
||||
|
||||
}
|
||||
burn_global_abort_level = -1;
|
||||
Cleanup_set_handlers(NULL, NULL, 2);
|
||||
|
||||
fprintf(stderr,"%sABORT : Trying to shut down drive and library\n",
|
||||
abort_message_prefix);
|
||||
fprintf(stderr,
|
||||
@ -219,28 +477,123 @@ int burn_builtin_abort_handler(void *handle, int signum, int flag)
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/* ts A61002 : API */
|
||||
void burn_set_signal_handling(void *handle, burn_abort_handler_t handler,
|
||||
int mode)
|
||||
int mode)
|
||||
{
|
||||
if(handler == NULL && mode == 0) {
|
||||
|
||||
/*
|
||||
fprintf(stderr, "libburn_experimental: burn_set_signal_handling, handler==%lx mode=%d\n", (unsigned long) handler, mode);
|
||||
*/
|
||||
|
||||
if(handler == NULL) {
|
||||
handler = burn_builtin_abort_handler;
|
||||
/*
|
||||
fprintf(stderr, "libburn_experimental: activated burn_builtin_abort_handler() with handle '%s'\n",(handle==NULL ? "libburn : " : (char *) handle));
|
||||
if ((mode & ~4) == 0)
|
||||
fprintf(stderr, "libburn_experimental: activated burn_builtin_abort_handler() with handle '%s'\n",(handle==NULL ? "libburn : " : (char *) handle));
|
||||
*/
|
||||
|
||||
}
|
||||
strcpy(abort_message_prefix, "libburn : ");
|
||||
if(handle != NULL)
|
||||
abort_message_prefix[0] = 0;
|
||||
if(handle != NULL && handler == burn_builtin_abort_handler)
|
||||
strncpy(abort_message_prefix, (char *) handle,
|
||||
sizeof(abort_message_prefix)-1);
|
||||
abort_message_prefix[sizeof(abort_message_prefix)-1] = 0;
|
||||
abort_control_pid= getpid();
|
||||
Cleanup_set_handlers(handle, (Cleanup_app_handler_T) handler, mode|4);
|
||||
abort_control_pid = getpid();
|
||||
abort_control_thread = pthread_self();
|
||||
burn_builtin_signal_action = (mode >> 4) & 15;
|
||||
if((mode & 11) != 0)
|
||||
burn_builtin_signal_action = 0;
|
||||
if(burn_builtin_signal_action > 1)
|
||||
burn_builtin_triggered_action = 0;
|
||||
if(burn_builtin_signal_action == 0)
|
||||
burn_builtin_signal_action = 1;
|
||||
Cleanup_set_handlers(handle, (Cleanup_app_handler_T) handler,
|
||||
(mode & 15) | 4);
|
||||
burn_global_signal_handle = handle;
|
||||
burn_global_signal_handler = handler;
|
||||
}
|
||||
|
||||
|
||||
/* ts B00304 : API */
|
||||
int burn_is_aborting(int flag)
|
||||
{
|
||||
return burn_builtin_triggered_action;
|
||||
}
|
||||
|
||||
|
||||
/* ts B00225 */
|
||||
/* @return 0= no abort action 2 pending , 1= not control thread
|
||||
*/
|
||||
int burn_init_catch_on_abort(int flag)
|
||||
{
|
||||
if (burn_builtin_triggered_action != 2)
|
||||
return 0;
|
||||
if (abort_control_pid != getpid() ||
|
||||
abort_control_thread != pthread_self())
|
||||
return 1;
|
||||
burn_abort(4440, burn_abort_pacifier, abort_message_prefix);
|
||||
fprintf(stderr,
|
||||
"\n%sABORT : Program done. Even if you do not see a shell prompt.\n\n",
|
||||
abort_message_prefix);
|
||||
exit(1);
|
||||
}
|
||||
|
||||
|
||||
/* ts A70223 : API */
|
||||
void burn_allow_untested_profiles(int yes)
|
||||
{
|
||||
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;
|
||||
}
|
||||
|
||||
|
||||
/* ts A91111 API */
|
||||
void burn_set_scsi_logging(int flag)
|
||||
{
|
||||
burn_sg_log_scsi = flag & 7;
|
||||
}
|
||||
|
||||
|
||||
/* ts B10312 API */
|
||||
void burn_allow_drive_role_4(int allowed)
|
||||
{
|
||||
burn_drive_role_4_allowed = (allowed & 0xf);
|
||||
}
|
||||
|
||||
|
||||
/* ts B10606 */
|
||||
void *burn_alloc_mem(size_t size, size_t count, int flag)
|
||||
{
|
||||
void *pt;
|
||||
|
||||
pt = calloc(size, count);
|
||||
if(pt == NULL)
|
||||
libdax_msgs_submit(libdax_messenger, -1, 0x00000003,
|
||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Out of virtual memory", 0, 0);
|
||||
return pt;
|
||||
}
|
||||
|
||||
|
@ -5,4 +5,41 @@
|
||||
|
||||
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;
|
||||
|
||||
extern int burn_builtin_signal_action; /* burn_set_signal_handling() */
|
||||
extern volatile int burn_builtin_triggered_action; /* burn_is_aborting() */
|
||||
|
||||
|
||||
/* ts B00225 */
|
||||
/* @return 0= no abort pending , 1= not control thread ,
|
||||
-1= surprisingly burn_abort returned
|
||||
*/
|
||||
int burn_init_catch_on_abort(int flag);
|
||||
|
||||
/* ts B10606 */
|
||||
void *burn_alloc_mem(size_t size, size_t count, int flag);
|
||||
|
||||
#define BURN_ALLOC_MEM(pt, typ, count) { \
|
||||
pt= (typ *) burn_alloc_mem(sizeof(typ), (size_t) (count), 0); \
|
||||
if(pt == NULL) { \
|
||||
ret= -1; goto ex; \
|
||||
} }
|
||||
|
||||
#define BURN_FREE_MEM(pt) { \
|
||||
if(pt != NULL) \
|
||||
free((char *) pt); \
|
||||
}
|
||||
|
||||
|
||||
#endif /* BURN__INIT_H */
|
||||
|
451
libburn/lec.c
451
libburn/lec.c
@ -1,451 +0,0 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
/* borrowed HEAVILY from cdrdao */
|
||||
|
||||
#include <string.h>
|
||||
#include "lec.h"
|
||||
|
||||
#define LEC_HEADER_OFFSET 12
|
||||
#define LEC_MODE1_P_PARITY_OFFSET 2076
|
||||
#define LEC_MODE1_Q_PARITY_OFFSET 2248
|
||||
|
||||
static unsigned char gf8_ilog[255] = {
|
||||
1, 2, 4, 8, 16, 32, 64, 128, 29, 58, 116, 232, 205, 135, 19, 38, 76,
|
||||
152, 45, 90, 180, 117, 234, 201, 143, 3, 6, 12, 24, 48, 96,
|
||||
192, 157, 39, 78, 156, 37, 74, 148, 53, 106, 212, 181, 119,
|
||||
238, 193, 159, 35, 70, 140, 5, 10, 20, 40, 80, 160, 93, 186,
|
||||
105, 210, 185, 111, 222, 161, 95, 190, 97, 194, 153, 47, 94,
|
||||
188, 101, 202, 137, 15, 30, 60, 120, 240, 253, 231, 211, 187,
|
||||
107, 214, 177, 127, 254, 225, 223, 163, 91, 182, 113, 226, 217,
|
||||
175, 67, 134, 17, 34, 68, 136, 13, 26, 52, 104, 208, 189, 103,
|
||||
206, 129, 31, 62, 124, 248, 237, 199, 147, 59, 118, 236, 197,
|
||||
151, 51, 102, 204, 133, 23, 46, 92, 184, 109, 218, 169, 79,
|
||||
158, 33, 66, 132, 21, 42, 84, 168, 77, 154, 41, 82, 164, 85,
|
||||
170, 73, 146, 57, 114, 228, 213, 183, 115, 230, 209, 191, 99,
|
||||
198, 145, 63, 126, 252, 229, 215, 179, 123, 246, 241, 255, 227,
|
||||
219, 171, 75, 150, 49, 98, 196, 149, 55, 110, 220, 165, 87,
|
||||
174, 65, 130, 25, 50, 100, 200, 141, 7, 14, 28, 56, 112, 224,
|
||||
221, 167, 83, 166, 81, 162, 89, 178, 121, 242, 249, 239, 195,
|
||||
155, 43, 86, 172, 69, 138, 9, 18, 36, 72, 144, 61, 122, 244,
|
||||
245, 247, 243, 251, 235, 203, 139, 11, 22, 44, 88, 176, 125,
|
||||
250, 233, 207, 131, 27, 54, 108, 216, 173, 71, 142,
|
||||
};
|
||||
static unsigned char gf8_log[256] = {
|
||||
0, 0, 1, 25, 2, 50, 26, 198, 3, 223, 51, 238, 27, 104, 199, 75, 4, 100,
|
||||
224, 14, 52, 141, 239, 129, 28, 193, 105, 248, 200, 8, 76, 113,
|
||||
5, 138, 101, 47, 225, 36, 15, 33, 53, 147, 142, 218, 240, 18,
|
||||
130, 69, 29, 181, 194, 125, 106, 39, 249, 185, 201, 154, 9,
|
||||
120, 77, 228, 114, 166, 6, 191, 139, 98, 102, 221, 48, 253,
|
||||
226, 152, 37, 179, 16, 145, 34, 136, 54, 208, 148, 206, 143,
|
||||
150, 219, 189, 241, 210, 19, 92, 131, 56, 70, 64, 30, 66, 182,
|
||||
163, 195, 72, 126, 110, 107, 58, 40, 84, 250, 133, 186, 61,
|
||||
202, 94, 155, 159, 10, 21, 121, 43, 78, 212, 229, 172, 115,
|
||||
243, 167, 87, 7, 112, 192, 247, 140, 128, 99, 13, 103, 74, 222,
|
||||
237, 49, 197, 254, 24, 227, 165, 153, 119, 38, 184, 180, 124,
|
||||
17, 68, 146, 217, 35, 32, 137, 46, 55, 63, 209, 91, 149, 188,
|
||||
207, 205, 144, 135, 151, 178, 220, 252, 190, 97, 242, 86, 211,
|
||||
171, 20, 42, 93, 158, 132, 60, 57, 83, 71, 109, 65, 162, 31,
|
||||
45, 67, 216, 183, 123, 164, 118, 196, 23, 73, 236, 127, 12,
|
||||
111, 246, 108, 161, 59, 82, 41, 157, 85, 170, 251, 96, 134,
|
||||
177, 187, 204, 62, 90, 203, 89, 95, 176, 156, 169, 160, 81, 11,
|
||||
245, 22, 235, 122, 117, 44, 215, 79, 174, 213, 233, 230, 231,
|
||||
173, 232, 116, 214, 244, 234, 168, 80, 88, 175,
|
||||
};
|
||||
static unsigned char gf8_q_coeffs[2][45] = {
|
||||
{97, 251, 133, 60, 82, 160, 155, 201, 8, 112, 246, 11, 21, 42, 157,
|
||||
169, 80, 174, 232, 230, 172, 211, 241, 18, 68, 216, 44, 121, 9, 200,
|
||||
75, 103, 221, 252, 96, 176, 88, 167, 114, 76, 199, 26, 1, 0, 0},
|
||||
{190, 96, 250, 132, 59, 81, 159, 154, 200, 7, 111, 245, 10, 20, 41,
|
||||
156, 168, 79, 173, 231, 229, 171, 210, 240, 17, 67, 215, 43, 120, 8,
|
||||
199, 74, 102, 220, 251, 95, 175, 87, 166, 113, 75, 198, 25, 0, 0}
|
||||
};
|
||||
static unsigned char gf8_p_coeffs[2][26] = {
|
||||
{230, 172, 211, 241, 18, 68, 216, 44, 121, 9, 200, 75, 103, 221, 252,
|
||||
96, 176, 88, 167, 114, 76, 199, 26, 1, 0, 0},
|
||||
{231, 229, 171, 210, 240, 17, 67, 215, 43, 120, 8, 199, 74, 102, 220,
|
||||
251, 95, 175, 87, 166, 113, 75, 198, 25, 0, 0}
|
||||
};
|
||||
|
||||
static unsigned char yellowbook_scrambler[2340] = {
|
||||
1, 128, 0, 96, 0, 40, 0, 30, 128, 8, 96, 6, 168, 2, 254, 129, 128, 96,
|
||||
96, 40, 40, 30, 158,
|
||||
136, 104, 102, 174, 170, 252, 127, 1, 224, 0, 72, 0, 54, 128, 22, 224,
|
||||
14, 200, 4, 86, 131, 126, 225,
|
||||
224, 72, 72, 54, 182, 150, 246, 238, 198, 204, 82, 213, 253, 159, 1,
|
||||
168, 0, 126, 128, 32, 96, 24, 40,
|
||||
10, 158, 135, 40, 98, 158, 169, 168, 126, 254, 160, 64, 120, 48, 34,
|
||||
148, 25, 175, 74, 252, 55, 1, 214,
|
||||
128, 94, 224, 56, 72, 18, 182, 141, 182, 229, 182, 203, 54, 215, 86,
|
||||
222, 190, 216, 112, 90, 164, 59, 59,
|
||||
83, 83, 125, 253, 225, 129, 136, 96, 102, 168, 42, 254, 159, 0, 104, 0,
|
||||
46, 128, 28, 96, 9, 232, 6,
|
||||
206, 130, 212, 97, 159, 104, 104, 46, 174, 156, 124, 105, 225, 238,
|
||||
200, 76, 86, 181, 254, 247, 0, 70, 128,
|
||||
50, 224, 21, 136, 15, 38, 132, 26, 227, 75, 9, 247, 70, 198, 178, 210,
|
||||
245, 157, 135, 41, 162, 158, 249,
|
||||
168, 66, 254, 177, 128, 116, 96, 39, 104, 26, 174, 139, 60, 103, 81,
|
||||
234, 188, 79, 49, 244, 20, 71, 79,
|
||||
114, 180, 37, 183, 91, 54, 187, 86, 243, 126, 197, 224, 83, 8, 61, 198,
|
||||
145, 146, 236, 109, 141, 237, 165,
|
||||
141, 187, 37, 179, 91, 53, 251, 87, 3, 126, 129, 224, 96, 72, 40, 54,
|
||||
158, 150, 232, 110, 206, 172, 84,
|
||||
125, 255, 97, 128, 40, 96, 30, 168, 8, 126, 134, 160, 98, 248, 41, 130,
|
||||
158, 225, 168, 72, 126, 182, 160,
|
||||
118, 248, 38, 194, 154, 209, 171, 28, 127, 73, 224, 54, 200, 22, 214,
|
||||
142, 222, 228, 88, 75, 122, 183, 99,
|
||||
54, 169, 214, 254, 222, 192, 88, 80, 58, 188, 19, 49, 205, 212, 85,
|
||||
159, 127, 40, 32, 30, 152, 8, 106,
|
||||
134, 175, 34, 252, 25, 129, 202, 224, 87, 8, 62, 134, 144, 98, 236, 41,
|
||||
141, 222, 229, 152, 75, 42, 183,
|
||||
95, 54, 184, 22, 242, 142, 197, 164, 83, 59, 125, 211, 97, 157, 232,
|
||||
105, 142, 174, 228, 124, 75, 97, 247,
|
||||
104, 70, 174, 178, 252, 117, 129, 231, 32, 74, 152, 55, 42, 150, 159,
|
||||
46, 232, 28, 78, 137, 244, 102, 199,
|
||||
106, 210, 175, 29, 188, 9, 177, 198, 244, 82, 199, 125, 146, 161, 173,
|
||||
184, 125, 178, 161, 181, 184, 119, 50,
|
||||
166, 149, 186, 239, 51, 12, 21, 197, 207, 19, 20, 13, 207, 69, 148, 51,
|
||||
47, 85, 220, 63, 25, 208, 10,
|
||||
220, 7, 25, 194, 138, 209, 167, 28, 122, 137, 227, 38, 201, 218, 214,
|
||||
219, 30, 219, 72, 91, 118, 187, 102,
|
||||
243, 106, 197, 239, 19, 12, 13, 197, 197, 147, 19, 45, 205, 221, 149,
|
||||
153, 175, 42, 252, 31, 1, 200, 0,
|
||||
86, 128, 62, 224, 16, 72, 12, 54, 133, 214, 227, 30, 201, 200, 86, 214,
|
||||
190, 222, 240, 88, 68, 58, 179,
|
||||
83, 53, 253, 215, 1, 158, 128, 104, 96, 46, 168, 28, 126, 137, 224,
|
||||
102, 200, 42, 214, 159, 30, 232, 8,
|
||||
78, 134, 180, 98, 247, 105, 134, 174, 226, 252, 73, 129, 246, 224, 70,
|
||||
200, 50, 214, 149, 158, 239, 40, 76,
|
||||
30, 181, 200, 119, 22, 166, 142, 250, 228, 67, 11, 113, 199, 100, 82,
|
||||
171, 125, 191, 97, 176, 40, 116, 30,
|
||||
167, 72, 122, 182, 163, 54, 249, 214, 194, 222, 209, 152, 92, 106, 185,
|
||||
239, 50, 204, 21, 149, 207, 47, 20,
|
||||
28, 15, 73, 196, 54, 211, 86, 221, 254, 217, 128, 90, 224, 59, 8, 19,
|
||||
70, 141, 242, 229, 133, 139, 35,
|
||||
39, 89, 218, 186, 219, 51, 27, 85, 203, 127, 23, 96, 14, 168, 4, 126,
|
||||
131, 96, 97, 232, 40, 78, 158,
|
||||
180, 104, 119, 110, 166, 172, 122, 253, 227, 1, 137, 192, 102, 208, 42,
|
||||
220, 31, 25, 200, 10, 214, 135, 30,
|
||||
226, 136, 73, 166, 182, 250, 246, 195, 6, 209, 194, 220, 81, 153, 252,
|
||||
106, 193, 239, 16, 76, 12, 53, 197,
|
||||
215, 19, 30, 141, 200, 101, 150, 171, 46, 255, 92, 64, 57, 240, 18,
|
||||
196, 13, 147, 69, 173, 243, 61, 133,
|
||||
209, 163, 28, 121, 201, 226, 214, 201, 158, 214, 232, 94, 206, 184, 84,
|
||||
114, 191, 101, 176, 43, 52, 31, 87,
|
||||
72, 62, 182, 144, 118, 236, 38, 205, 218, 213, 155, 31, 43, 72, 31,
|
||||
118, 136, 38, 230, 154, 202, 235, 23,
|
||||
15, 78, 132, 52, 99, 87, 105, 254, 174, 192, 124, 80, 33, 252, 24, 65,
|
||||
202, 176, 87, 52, 62, 151, 80,
|
||||
110, 188, 44, 113, 221, 228, 89, 139, 122, 231, 99, 10, 169, 199, 62,
|
||||
210, 144, 93, 172, 57, 189, 210, 241,
|
||||
157, 132, 105, 163, 110, 249, 236, 66, 205, 241, 149, 132, 111, 35,
|
||||
108, 25, 237, 202, 205, 151, 21, 174, 143,
|
||||
60, 100, 17, 235, 76, 79, 117, 244, 39, 7, 90, 130, 187, 33, 179, 88,
|
||||
117, 250, 167, 3, 58, 129, 211,
|
||||
32, 93, 216, 57, 154, 146, 235, 45, 143, 93, 164, 57, 187, 82, 243,
|
||||
125, 133, 225, 163, 8, 121, 198, 162,
|
||||
210, 249, 157, 130, 233, 161, 142, 248, 100, 66, 171, 113, 191, 100,
|
||||
112, 43, 100, 31, 107, 72, 47, 118, 156,
|
||||
38, 233, 218, 206, 219, 20, 91, 79, 123, 116, 35, 103, 89, 234, 186,
|
||||
207, 51, 20, 21, 207, 79, 20, 52,
|
||||
15, 87, 68, 62, 179, 80, 117, 252, 39, 1, 218, 128, 91, 32, 59, 88, 19,
|
||||
122, 141, 227, 37, 137, 219,
|
||||
38, 219, 90, 219, 123, 27, 99, 75, 105, 247, 110, 198, 172, 82, 253,
|
||||
253, 129, 129, 160, 96, 120, 40, 34,
|
||||
158, 153, 168, 106, 254, 175, 0, 124, 0, 33, 192, 24, 80, 10, 188, 7,
|
||||
49, 194, 148, 81, 175, 124, 124,
|
||||
33, 225, 216, 72, 90, 182, 187, 54, 243, 86, 197, 254, 211, 0, 93, 192,
|
||||
57, 144, 18, 236, 13, 141, 197,
|
||||
165, 147, 59, 45, 211, 93, 157, 249, 169, 130, 254, 225, 128, 72, 96,
|
||||
54, 168, 22, 254, 142, 192, 100, 80,
|
||||
43, 124, 31, 97, 200, 40, 86, 158, 190, 232, 112, 78, 164, 52, 123, 87,
|
||||
99, 126, 169, 224, 126, 200, 32,
|
||||
86, 152, 62, 234, 144, 79, 44, 52, 29, 215, 73, 158, 182, 232, 118,
|
||||
206, 166, 212, 122, 223, 99, 24, 41,
|
||||
202, 158, 215, 40, 94, 158, 184, 104, 114, 174, 165, 188, 123, 49, 227,
|
||||
84, 73, 255, 118, 192, 38, 208, 26,
|
||||
220, 11, 25, 199, 74, 210, 183, 29, 182, 137, 182, 230, 246, 202, 198,
|
||||
215, 18, 222, 141, 152, 101, 170, 171,
|
||||
63, 63, 80, 16, 60, 12, 17, 197, 204, 83, 21, 253, 207, 1, 148, 0, 111,
|
||||
64, 44, 48, 29, 212, 9,
|
||||
159, 70, 232, 50, 206, 149, 148, 111, 47, 108, 28, 45, 201, 221, 150,
|
||||
217, 174, 218, 252, 91, 1, 251, 64,
|
||||
67, 112, 49, 228, 20, 75, 79, 119, 116, 38, 167, 90, 250, 187, 3, 51,
|
||||
65, 213, 240, 95, 4, 56, 3,
|
||||
82, 129, 253, 160, 65, 184, 48, 114, 148, 37, 175, 91, 60, 59, 81, 211,
|
||||
124, 93, 225, 249, 136, 66, 230,
|
||||
177, 138, 244, 103, 7, 106, 130, 175, 33, 188, 24, 113, 202, 164, 87,
|
||||
59, 126, 147, 96, 109, 232, 45, 142,
|
||||
157, 164, 105, 187, 110, 243, 108, 69, 237, 243, 13, 133, 197, 163, 19,
|
||||
57, 205, 210, 213, 157, 159, 41, 168,
|
||||
30, 254, 136, 64, 102, 176, 42, 244, 31, 7, 72, 2, 182, 129, 182, 224,
|
||||
118, 200, 38, 214, 154, 222, 235,
|
||||
24, 79, 74, 180, 55, 55, 86, 150, 190, 238, 240, 76, 68, 53, 243, 87,
|
||||
5, 254, 131, 0, 97, 192, 40,
|
||||
80, 30, 188, 8, 113, 198, 164, 82, 251, 125, 131, 97, 161, 232, 120,
|
||||
78, 162, 180, 121, 183, 98, 246, 169,
|
||||
134, 254, 226, 192, 73, 144, 54, 236, 22, 205, 206, 213, 148, 95, 47,
|
||||
120, 28, 34, 137, 217, 166, 218, 250,
|
||||
219, 3, 27, 65, 203, 112, 87, 100, 62, 171, 80, 127, 124, 32, 33, 216,
|
||||
24, 90, 138, 187, 39, 51, 90,
|
||||
149, 251, 47, 3, 92, 1, 249, 192, 66, 208, 49, 156, 20, 105, 207, 110,
|
||||
212, 44, 95, 93, 248, 57, 130,
|
||||
146, 225, 173, 136, 125, 166, 161, 186, 248, 115, 2, 165, 193, 187, 16,
|
||||
115, 76, 37, 245, 219, 7, 27, 66,
|
||||
139, 113, 167, 100, 122, 171, 99, 63, 105, 208, 46, 220, 28, 89, 201,
|
||||
250, 214, 195, 30, 209, 200, 92, 86,
|
||||
185, 254, 242, 192, 69, 144, 51, 44, 21, 221, 207, 25, 148, 10, 239,
|
||||
71, 12, 50, 133, 213, 163, 31, 57,
|
||||
200, 18, 214, 141, 158, 229, 168, 75, 62, 183, 80, 118, 188, 38, 241,
|
||||
218, 196, 91, 19, 123, 77, 227, 117,
|
||||
137, 231, 38, 202, 154, 215, 43, 30, 159, 72, 104, 54, 174, 150, 252,
|
||||
110, 193, 236, 80, 77, 252, 53, 129,
|
||||
215, 32, 94, 152, 56, 106, 146, 175, 45, 188, 29, 177, 201, 180, 86,
|
||||
247, 126, 198, 160, 82, 248, 61, 130,
|
||||
145, 161, 172, 120, 125, 226, 161, 137, 184, 102, 242, 170, 197, 191,
|
||||
19, 48, 13, 212, 5, 159, 67, 40, 49,
|
||||
222, 148, 88, 111, 122, 172, 35, 61, 217, 209, 154, 220, 107, 25, 239,
|
||||
74, 204, 55, 21, 214, 143, 30, 228,
|
||||
8, 75, 70, 183, 114, 246, 165, 134, 251, 34, 195, 89, 145, 250, 236,
|
||||
67, 13, 241, 197, 132, 83, 35, 125,
|
||||
217, 225, 154, 200, 107, 22, 175, 78, 252, 52, 65, 215, 112, 94, 164,
|
||||
56, 123, 82, 163, 125, 185, 225, 178,
|
||||
200, 117, 150, 167, 46, 250, 156, 67, 41, 241, 222, 196, 88, 83, 122,
|
||||
189, 227, 49, 137, 212, 102, 223, 106,
|
||||
216, 47, 26, 156, 11, 41, 199, 94, 210, 184, 93, 178, 185, 181, 178,
|
||||
247, 53, 134, 151, 34, 238, 153, 140,
|
||||
106, 229, 239, 11, 12, 7, 69, 194, 179, 17, 181, 204, 119, 21, 230,
|
||||
143, 10, 228, 7, 11, 66, 135, 113,
|
||||
162, 164, 121, 187, 98, 243, 105, 133, 238, 227, 12, 73, 197, 246, 211,
|
||||
6, 221, 194, 217, 145, 154, 236, 107,
|
||||
13, 239, 69, 140, 51, 37, 213, 219, 31, 27, 72, 11, 118, 135, 102, 226,
|
||||
170, 201, 191, 22, 240, 14, 196,
|
||||
4, 83, 67, 125, 241, 225, 132, 72, 99, 118, 169, 230, 254, 202, 192,
|
||||
87, 16, 62, 140, 16, 101, 204, 43,
|
||||
21, 223, 79, 24, 52, 10, 151, 71, 46, 178, 156, 117, 169, 231, 62, 202,
|
||||
144, 87, 44, 62, 157, 208, 105,
|
||||
156, 46, 233, 220, 78, 217, 244, 90, 199, 123, 18, 163, 77, 185, 245,
|
||||
178, 199, 53, 146, 151, 45, 174, 157,
|
||||
188, 105, 177, 238, 244, 76, 71, 117, 242, 167, 5, 186, 131, 51, 33,
|
||||
213, 216, 95, 26, 184, 11, 50, 135,
|
||||
85, 162, 191, 57, 176, 18, 244, 13, 135, 69, 162, 179, 57, 181, 210,
|
||||
247, 29, 134, 137, 162, 230, 249, 138,
|
||||
194, 231, 17, 138, 140, 103, 37, 234, 155, 15, 43, 68, 31, 115, 72, 37,
|
||||
246, 155, 6, 235, 66, 207, 113,
|
||||
148, 36, 111, 91, 108, 59, 109, 211, 109, 157, 237, 169, 141, 190, 229,
|
||||
176, 75, 52, 55, 87, 86, 190, 190,
|
||||
240, 112, 68, 36, 51, 91, 85, 251, 127, 3, 96, 1, 232, 0, 78, 128, 52,
|
||||
96, 23, 104, 14, 174, 132,
|
||||
124, 99, 97, 233, 232, 78, 206, 180, 84, 119, 127, 102, 160, 42, 248,
|
||||
31, 2, 136, 1, 166, 128, 122, 224,
|
||||
35, 8, 25, 198, 138, 210, 231, 29, 138, 137, 167, 38, 250, 154, 195,
|
||||
43, 17, 223, 76, 88, 53, 250, 151,
|
||||
3, 46, 129, 220, 96, 89, 232, 58, 206, 147, 20, 109, 207, 109, 148, 45,
|
||||
175, 93, 188, 57, 177, 210, 244,
|
||||
93, 135, 121, 162, 162, 249, 185, 130, 242, 225, 133, 136, 99, 38, 169,
|
||||
218, 254, 219, 0, 91, 64, 59, 112,
|
||||
19, 100, 13, 235, 69, 143, 115, 36, 37, 219, 91, 27, 123, 75, 99, 119,
|
||||
105, 230, 174, 202, 252, 87, 1,
|
||||
254, 128, 64, 96, 48, 40, 20, 30, 143, 72, 100, 54, 171, 86, 255, 126,
|
||||
192, 32, 80, 24, 60, 10, 145,
|
||||
199, 44, 82, 157, 253, 169, 129, 190, 224, 112, 72, 36, 54, 155, 86,
|
||||
235, 126, 207, 96, 84, 40, 63, 94,
|
||||
144, 56, 108, 18, 173, 205, 189, 149, 177, 175, 52, 124, 23, 97, 206,
|
||||
168, 84, 126, 191, 96, 112, 40, 36,
|
||||
30, 155, 72, 107, 118, 175, 102, 252, 42, 193, 223, 16, 88, 12, 58,
|
||||
133, 211, 35, 29, 217, 201, 154, 214,
|
||||
235, 30, 207, 72, 84, 54, 191, 86, 240, 62, 196, 16, 83, 76, 61, 245,
|
||||
209, 135, 28, 98, 137, 233, 166,
|
||||
206, 250, 212, 67, 31, 113, 200, 36, 86, 155, 126, 235, 96, 79, 104,
|
||||
52, 46, 151, 92, 110, 185, 236, 114,
|
||||
205, 229, 149, 139, 47, 39, 92, 26, 185, 203, 50, 215, 85, 158, 191,
|
||||
40, 112, 30, 164, 8, 123, 70, 163,
|
||||
114, 249, 229, 130, 203, 33, 151, 88, 110, 186, 172, 115, 61, 229, 209,
|
||||
139, 28, 103, 73, 234, 182, 207, 54,
|
||||
212, 22, 223, 78, 216, 52, 90, 151, 123, 46, 163, 92, 121, 249, 226,
|
||||
194, 201, 145, 150, 236, 110, 205, 236,
|
||||
85, 141, 255, 37, 128, 27, 32, 11, 88, 7, 122, 130, 163, 33, 185, 216,
|
||||
114, 218, 165, 155, 59, 43, 83,
|
||||
95, 125, 248, 33, 130, 152, 97, 170, 168, 127, 62, 160, 16, 120, 12,
|
||||
34, 133, 217, 163, 26, 249, 203, 2,
|
||||
215, 65, 158, 176, 104, 116, 46, 167, 92, 122, 185, 227, 50, 201, 213,
|
||||
150, 223, 46, 216, 28, 90, 137, 251,
|
||||
38, 195, 90, 209, 251, 28, 67, 73, 241, 246, 196, 70, 211, 114, 221,
|
||||
229, 153,
|
||||
};
|
||||
|
||||
void scramble(unsigned char *inout)
|
||||
{
|
||||
unsigned char *r = inout + 12;
|
||||
unsigned char *s = yellowbook_scrambler;
|
||||
unsigned int i;
|
||||
|
||||
for (i = 2340; i; i--) {
|
||||
*r++ ^= *s++;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate the P parities for the sector.
|
||||
* The 43 P vectors of length 24 are combined with the GF8_P_COEFFS.
|
||||
*/
|
||||
void parity_p(unsigned char *sector)
|
||||
{
|
||||
int i, j;
|
||||
unsigned char p0_msb, p1_msb;
|
||||
unsigned char p0_lsb, p1_lsb;
|
||||
unsigned char *p_msb_start, *p_lsb_start;
|
||||
unsigned char *p_msb, *p_lsb;
|
||||
unsigned char *coeffs0, *coeffs1;
|
||||
unsigned char *p0, *p1;
|
||||
unsigned char d;
|
||||
unsigned short c;
|
||||
|
||||
p_lsb_start = sector + LEC_HEADER_OFFSET;
|
||||
p_msb_start = sector + LEC_HEADER_OFFSET + 1;
|
||||
|
||||
p1 = sector + LEC_MODE1_P_PARITY_OFFSET;
|
||||
p0 = sector + LEC_MODE1_P_PARITY_OFFSET + 2 * 43;
|
||||
|
||||
for (i = 0; i <= 42; i++) {
|
||||
p_lsb = p_lsb_start;
|
||||
p_msb = p_msb_start;
|
||||
|
||||
coeffs0 = gf8_p_coeffs[0];
|
||||
coeffs1 = gf8_p_coeffs[1];
|
||||
|
||||
p0_lsb = p1_lsb = p0_msb = p1_msb = 0;
|
||||
|
||||
for (j = 0; j <= 23; j++) {
|
||||
d = *p_lsb;
|
||||
|
||||
if (d != 0) {
|
||||
c = gf8_log[d] + *coeffs0;
|
||||
if (c >= 255)
|
||||
c -= 255;
|
||||
p0_lsb ^= gf8_ilog[c];
|
||||
|
||||
c = gf8_log[d] + *coeffs1;
|
||||
if (c >= 255)
|
||||
c -= 255;
|
||||
p1_lsb ^= gf8_ilog[c];
|
||||
}
|
||||
|
||||
d = *p_msb;
|
||||
|
||||
if (d != 0) {
|
||||
c = gf8_log[d] + *coeffs0;
|
||||
if (c >= 255)
|
||||
c -= 255;
|
||||
p0_msb ^= gf8_ilog[c];
|
||||
|
||||
c = gf8_log[d] + *coeffs1;
|
||||
if (c >= 255)
|
||||
c -= 255;
|
||||
p1_msb ^= gf8_ilog[c];
|
||||
}
|
||||
|
||||
coeffs0++;
|
||||
coeffs1++;
|
||||
|
||||
p_lsb += 2 * 43;
|
||||
p_msb += 2 * 43;
|
||||
}
|
||||
|
||||
*p0 = p0_lsb;
|
||||
*(p0 + 1) = p0_msb;
|
||||
|
||||
*p1 = p1_lsb;
|
||||
*(p1 + 1) = p1_msb;
|
||||
|
||||
p0 += 2;
|
||||
p1 += 2;
|
||||
|
||||
p_lsb_start += 2;
|
||||
p_msb_start += 2;
|
||||
}
|
||||
}
|
||||
|
||||
/* Calculate the Q parities for the sector.
|
||||
* The 26 Q vectors of length 43 are combined with the GF8_Q_COEFFS.
|
||||
*/
|
||||
void parity_q(unsigned char *sector)
|
||||
{
|
||||
int i, j;
|
||||
unsigned char q0_msb, q1_msb;
|
||||
unsigned char q0_lsb, q1_lsb;
|
||||
unsigned char *q_msb_start, *q_lsb_start;
|
||||
unsigned char *q_msb, *q_lsb;
|
||||
unsigned char *coeffs0, *coeffs1;
|
||||
unsigned char *q0, *q1, *q_start;
|
||||
unsigned char d;
|
||||
unsigned short c;
|
||||
|
||||
q_lsb_start = sector + LEC_HEADER_OFFSET;
|
||||
q_msb_start = sector + LEC_HEADER_OFFSET + 1;
|
||||
|
||||
q_start = sector + LEC_MODE1_Q_PARITY_OFFSET;
|
||||
q1 = sector + LEC_MODE1_Q_PARITY_OFFSET;
|
||||
q0 = sector + LEC_MODE1_Q_PARITY_OFFSET + 2 * 26;
|
||||
|
||||
for (i = 0; i <= 25; i++) {
|
||||
q_lsb = q_lsb_start;
|
||||
q_msb = q_msb_start;
|
||||
|
||||
coeffs0 = gf8_q_coeffs[0];
|
||||
coeffs1 = gf8_q_coeffs[1];
|
||||
|
||||
q0_lsb = q1_lsb = q0_msb = q1_msb = 0;
|
||||
|
||||
for (j = 0; j <= 42; j++) {
|
||||
d = *q_lsb;
|
||||
|
||||
if (d != 0) {
|
||||
c = gf8_log[d] + *coeffs0;
|
||||
if (c >= 255)
|
||||
c -= 255;
|
||||
q0_lsb ^= gf8_ilog[c];
|
||||
|
||||
c = gf8_log[d] + *coeffs1;
|
||||
if (c >= 255)
|
||||
c -= 255;
|
||||
q1_lsb ^= gf8_ilog[c];
|
||||
}
|
||||
|
||||
d = *q_msb;
|
||||
|
||||
if (d != 0) {
|
||||
c = gf8_log[d] + *coeffs0;
|
||||
if (c >= 255)
|
||||
c -= 255;
|
||||
q0_msb ^= gf8_ilog[c];
|
||||
|
||||
c = gf8_log[d] + *coeffs1;
|
||||
if (c >= 255)
|
||||
c -= 255;
|
||||
q1_msb ^= gf8_ilog[c];
|
||||
}
|
||||
|
||||
coeffs0++;
|
||||
coeffs1++;
|
||||
|
||||
q_lsb += 2 * 44;
|
||||
q_msb += 2 * 44;
|
||||
|
||||
if (q_lsb >= q_start) {
|
||||
q_msb -= 2 * 1118;
|
||||
q_lsb -= 2 * 1118;
|
||||
}
|
||||
}
|
||||
|
||||
*q0 = q0_lsb;
|
||||
*(q0 + 1) = q0_msb;
|
||||
|
||||
*q1 = q1_lsb;
|
||||
*(q1 + 1) = q1_msb;
|
||||
|
||||
q0 += 2;
|
||||
q1 += 2;
|
||||
|
||||
q_lsb_start += 2 * 43;
|
||||
q_msb_start += 2 * 43;
|
||||
}
|
||||
}
|
@ -1,12 +0,0 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
#ifndef __LEC
|
||||
#define __LEC
|
||||
|
||||
#define RS_L12_BITS 8
|
||||
|
||||
void scramble(unsigned char *);
|
||||
void parity_p(unsigned char *in);
|
||||
void parity_q(unsigned char *in);
|
||||
|
||||
#endif /* __LEC */
|
2314
libburn/libburn.h
2314
libburn/libburn.h
File diff suppressed because it is too large
Load Diff
170
libburn/libburn.ver
Normal file
170
libburn/libburn.ver
Normal file
@ -0,0 +1,170 @@
|
||||
LIBBURN4 {
|
||||
global:
|
||||
burn_abort;
|
||||
burn_abort_pacifier;
|
||||
burn_allow_drive_role_4;
|
||||
burn_allow_untested_profiles;
|
||||
burn_disc_add_session;
|
||||
burn_disc_available_space;
|
||||
burn_disc_close_damaged;
|
||||
burn_disc_create;
|
||||
burn_disc_erasable;
|
||||
burn_disc_erase;
|
||||
burn_disc_format;
|
||||
burn_disc_free;
|
||||
burn_disc_free_multi_caps;
|
||||
burn_disc_get_bd_spare_info;
|
||||
burn_disc_get_cd_info;
|
||||
burn_disc_get_format_descr;
|
||||
burn_disc_get_formats;
|
||||
burn_disc_get_media_id;
|
||||
burn_disc_get_msc1;
|
||||
burn_disc_get_multi_caps;
|
||||
burn_disc_get_profile;
|
||||
burn_disc_get_sectors;
|
||||
burn_disc_get_sessions;
|
||||
burn_disc_get_status;
|
||||
burn_disc_next_track_is_damaged;
|
||||
burn_disc_pretend_blank;
|
||||
burn_disc_pretend_full;
|
||||
burn_disc_read;
|
||||
burn_disc_read_atip;
|
||||
burn_disc_remove_session;
|
||||
burn_disc_track_lba_nwa;
|
||||
burn_disc_write;
|
||||
burn_drive_add_whitelist;
|
||||
burn_drive_cancel;
|
||||
burn_drive_clear_whitelist;
|
||||
burn_drive_convert_fs_adr;
|
||||
burn_drive_convert_scsi_adr;
|
||||
burn_drive_d_get_adr;
|
||||
burn_drive_equals_adr;
|
||||
burn_drive_free_speedlist;
|
||||
burn_drive_get_adr;
|
||||
burn_drive_get_all_profiles;
|
||||
burn_drive_get_best_speed;
|
||||
burn_drive_get_disc;
|
||||
burn_drive_get_drive_role;
|
||||
burn_drive_get_min_write_speed;
|
||||
burn_drive_get_read_speed;
|
||||
burn_drive_get_speedlist;
|
||||
burn_drive_get_start_end_lba;
|
||||
burn_drive_get_status;
|
||||
burn_drive_get_write_speed;
|
||||
burn_drive_grab;
|
||||
burn_drive_info_forget;
|
||||
burn_drive_info_free;
|
||||
burn_drive_is_enumerable_adr;
|
||||
burn_drive_leave_locked;
|
||||
burn_drive_obtain_scsi_adr;
|
||||
burn_drive_probe_cd_write_modes;
|
||||
burn_drive_release;
|
||||
burn_drive_scan;
|
||||
burn_drive_scan_and_grab;
|
||||
burn_drive_set_buffer_waiting;
|
||||
burn_drive_set_speed;
|
||||
burn_drive_set_stream_recording;
|
||||
burn_drive_snooze;
|
||||
burn_drive_wrote_well;
|
||||
burn_fd_source_new;
|
||||
burn_fifo_fill;
|
||||
burn_fifo_get_statistics;
|
||||
burn_fifo_inquire_status;
|
||||
burn_fifo_next_interval;
|
||||
burn_fifo_peek_data;
|
||||
burn_fifo_source_new;
|
||||
burn_file_source_new;
|
||||
burn_finish;
|
||||
burn_get_read_capacity;
|
||||
burn_guess_cd_manufacturer;
|
||||
burn_guess_manufacturer;
|
||||
burn_initialize;
|
||||
burn_is_aborting;
|
||||
burn_lba_to_msf;
|
||||
burn_msf_to_lba;
|
||||
burn_msf_to_sectors;
|
||||
burn_msgs_obtain;
|
||||
burn_msgs_set_severities;
|
||||
burn_msgs_submit;
|
||||
burn_obtain_profile_name;
|
||||
burn_offst_source_new;
|
||||
burn_os_alloc_buffer;
|
||||
burn_os_free_buffer;
|
||||
burn_os_open_track_src;
|
||||
burn_precheck_write;
|
||||
burn_preset_device_open;
|
||||
burn_random_access_write;
|
||||
burn_read_data;
|
||||
burn_read_opts_free;
|
||||
burn_read_opts_new;
|
||||
burn_read_opts_read_subcodes_audio;
|
||||
burn_read_opts_read_subcodes_data;
|
||||
burn_read_opts_report_recovered_errors;
|
||||
burn_read_opts_set_c2errors;
|
||||
burn_read_opts_set_hardware_error_recovery;
|
||||
burn_read_opts_set_hardware_error_retries;
|
||||
burn_read_opts_set_raw;
|
||||
burn_read_opts_transfer_damaged_blocks;
|
||||
burn_scsi_transport_id;
|
||||
burn_sectors_to_msf;
|
||||
burn_session_add_track;
|
||||
burn_session_create;
|
||||
burn_session_free;
|
||||
burn_session_get_hidefirst;
|
||||
burn_session_get_leadout_entry;
|
||||
burn_session_get_sectors;
|
||||
burn_session_get_tracks;
|
||||
burn_session_hide_first_track;
|
||||
burn_session_remove_track;
|
||||
burn_set_messenger;
|
||||
burn_set_scsi_logging;
|
||||
burn_set_signal_handling;
|
||||
burn_set_verbosity;
|
||||
burn_sev_to_text;
|
||||
burn_source_free;
|
||||
burn_structure_print_disc;
|
||||
burn_structure_print_session;
|
||||
burn_structure_print_track;
|
||||
burn_text_to_sev;
|
||||
burn_track_clear_isrc;
|
||||
burn_track_create;
|
||||
burn_track_define_data;
|
||||
burn_track_free;
|
||||
burn_track_get_counters;
|
||||
burn_track_get_entry;
|
||||
burn_track_get_mode;
|
||||
burn_track_get_sectors;
|
||||
burn_track_set_byte_swap;
|
||||
burn_track_set_cdxa_conv;
|
||||
burn_track_set_default_size;
|
||||
burn_track_set_isrc;
|
||||
burn_track_set_size;
|
||||
burn_track_set_source;
|
||||
burn_version;
|
||||
burn_write_opts_auto_write_type;
|
||||
burn_write_opts_free;
|
||||
burn_write_opts_get_drive;
|
||||
burn_write_opts_new;
|
||||
burn_write_opts_set_dvd_obs;
|
||||
burn_write_opts_set_fillup;
|
||||
burn_write_opts_set_force;
|
||||
burn_write_opts_set_format;
|
||||
burn_write_opts_set_has_mediacatalog;
|
||||
burn_write_opts_set_mediacatalog;
|
||||
burn_write_opts_set_multi;
|
||||
burn_write_opts_set_perform_opc;
|
||||
burn_write_opts_set_simulate;
|
||||
burn_write_opts_set_start_byte;
|
||||
burn_write_opts_set_stdio_fsync;
|
||||
burn_write_opts_set_stream_recording;
|
||||
burn_write_opts_set_toc_entries;
|
||||
burn_write_opts_set_underrun_proof;
|
||||
burn_write_opts_set_write_type;
|
||||
libdax_audioxtr_destroy;
|
||||
libdax_audioxtr_detach_fd;
|
||||
libdax_audioxtr_get_id;
|
||||
libdax_audioxtr_get_size;
|
||||
libdax_audioxtr_new;
|
||||
libdax_audioxtr_read;
|
||||
local: *;
|
||||
};
|
@ -1,9 +1,13 @@
|
||||
|
||||
/* libdax_audioxtr
|
||||
Audio track data extraction facility of libdax and libburn.
|
||||
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
|
||||
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
@ -21,7 +25,8 @@ extern struct libdax_msgs *libdax_messenger;
|
||||
/* Only this single source module is entitled to do this */
|
||||
#define LIBDAX_AUDIOXTR_H_INTERNAL 1
|
||||
|
||||
/* All clients of the extraction facility must do this */
|
||||
/* All clients of the extraction facility must do this or include libburn.h */
|
||||
#define LIBDAX_AUDIOXTR_H_PUBLIC 1
|
||||
#include "libdax_audioxtr.h"
|
||||
|
||||
|
||||
@ -30,11 +35,11 @@ int libdax_audioxtr_new(struct libdax_audioxtr **xtr, char *path, int flag)
|
||||
int ret= -1;
|
||||
struct libdax_audioxtr *o;
|
||||
|
||||
o= *xtr= (struct libdax_audioxtr *) malloc(sizeof(struct libdax_audioxtr));
|
||||
o= *xtr= (struct libdax_audioxtr *) calloc(1, sizeof(struct libdax_audioxtr));
|
||||
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;
|
||||
|
@ -1,12 +1,19 @@
|
||||
|
||||
/* libdax_audioxtr
|
||||
Audio track data extraction facility of libdax and libburn.
|
||||
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
|
||||
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
|
||||
*/
|
||||
|
||||
#ifndef LIBDAX_AUDIOXTR_H_INCLUDED
|
||||
#define LIBDAX_AUDIOXTR_H_INCLUDED 1
|
||||
|
||||
|
||||
/* Normally this public API is defined in <libburn/libburn.h>
|
||||
Macro LIBDAX_AUDIOXTR_H_PUBLIC enables the definition for programs
|
||||
which only include this file.
|
||||
*/
|
||||
#ifdef LIBDAX_AUDIOXTR_H_PUBLIC
|
||||
|
||||
/* Public Macros */
|
||||
|
||||
/* Maximum size for address paths and fmt_info strings */
|
||||
@ -110,15 +117,16 @@ int libdax_audioxtr_detach_fd(struct libdax_audioxtr *o, int *fd, int flag);
|
||||
*/
|
||||
int libdax_audioxtr_destroy(struct libdax_audioxtr **xtr, int flag);
|
||||
|
||||
#endif /* LIBDAX_AUDIOXTR_H_PUBLIC */
|
||||
|
||||
|
||||
#ifdef LIDBAX_AUDIOXTR________________
|
||||
#ifdef LIBDAX_AUDIOXTR________________
|
||||
|
||||
|
||||
-- place documentation text here ---
|
||||
|
||||
|
||||
#endif /* LIDBAX_AUDIOXTR_________________ */
|
||||
#endif /* LIBDAX_AUDIOXTR_________________ */
|
||||
|
||||
|
||||
|
||||
|
@ -1,9 +1,14 @@
|
||||
|
||||
/* libdax_msgs
|
||||
Message handling facility of libdax.
|
||||
Copyright (C) 2006 Thomas Schmitt <scdbackup@gmx.net>, provided under GPL
|
||||
Copyright (C) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>,
|
||||
provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <unistd.h>
|
||||
@ -11,6 +16,7 @@
|
||||
#include <stdlib.h>
|
||||
#include <errno.h>
|
||||
#include <sys/time.h>
|
||||
#include <pthread.h>
|
||||
|
||||
/* Only this single source module is entitled to do this */
|
||||
#define LIBDAX_MSGS_H_INTERNAL 1
|
||||
@ -31,7 +37,7 @@ static int libdax_msgs_item_new(struct libdax_msgs_item **item,
|
||||
struct timezone tz;
|
||||
|
||||
(*item)= o=
|
||||
(struct libdax_msgs_item *) malloc(sizeof(struct libdax_msgs_item));
|
||||
(struct libdax_msgs_item *) calloc(1, sizeof(struct libdax_msgs_item));
|
||||
if(o==NULL)
|
||||
return(-1);
|
||||
o->timestamp= 0.0;
|
||||
@ -39,7 +45,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 +114,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);
|
||||
}
|
||||
|
||||
@ -134,9 +140,10 @@ int libdax_msgs_new(struct libdax_msgs **m, int flag)
|
||||
{
|
||||
struct libdax_msgs *o;
|
||||
|
||||
(*m)= o= (struct libdax_msgs *) malloc(sizeof(struct libdax_msgs));
|
||||
(*m)= o= (struct libdax_msgs *) calloc(1, sizeof(struct libdax_msgs));
|
||||
if(o==NULL)
|
||||
return(-1);
|
||||
o->refcount= 1;
|
||||
o->oldest= NULL;
|
||||
o->youngest= NULL;
|
||||
o->count= 0;
|
||||
@ -152,43 +159,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 +189,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 +257,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 +273,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 +289,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 +299,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 +315,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 +327,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,12 +365,12 @@ 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;
|
||||
if(msg_text!=NULL) {
|
||||
item->msg_text= malloc(strlen(msg_text)+1);
|
||||
item->msg_text= calloc(1, strlen(msg_text)+1);
|
||||
if(item->msg_text==NULL)
|
||||
goto failed;
|
||||
strcpy(item->msg_text,msg_text);
|
||||
|
@ -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-2011 Thomas Schmitt <scdbackup@gmx.net>,
|
||||
provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
|
||||
@ -22,7 +23,7 @@ struct libdax_msgs_item {
|
||||
|
||||
double timestamp;
|
||||
pid_t process_id;
|
||||
int driveno;
|
||||
int origin;
|
||||
|
||||
int severity;
|
||||
int priority;
|
||||
@ -42,6 +43,8 @@ struct libdax_msgs_item {
|
||||
|
||||
struct libdax_msgs {
|
||||
|
||||
int refcount;
|
||||
|
||||
struct libdax_msgs_item *oldest;
|
||||
struct libdax_msgs_item *youngest;
|
||||
int count;
|
||||
@ -67,6 +70,31 @@ struct libdax_msgs {
|
||||
#ifndef LIBDAX_MSGS_H_INTERNAL
|
||||
|
||||
|
||||
/* Architectural aspects */
|
||||
/*
|
||||
libdax_msgs is designed to serve in libraries which want to offer their
|
||||
applications a way to control the output of library messages. It shall be
|
||||
incorporated by an owner, i.e. a software entity which encloses the code
|
||||
of the .c file.
|
||||
|
||||
Owner of libdax_msgs is libburn. A fully compatible variant named libiso_msgs
|
||||
is owned by libisofs and can get generated by a script of the libburn
|
||||
project: libburn/libdax_msgs_to_xyz_msgs.sh .
|
||||
|
||||
Reason: One cannot link two owners of the same variant together because
|
||||
both would offer the same functions to the linker. For that situation one
|
||||
has to create a compatible variant as it is done for libisofs.
|
||||
|
||||
Compatible variants may get plugged together by call combinations like
|
||||
burn_set_messenger(iso_get_messenger());
|
||||
A new variant would demand a _set_messenger() function if it has to work
|
||||
with libisofs. If only libburn is planned as link partner then a simple
|
||||
_get_messenger() does suffice.
|
||||
Take care to shutdown libburn before its provider of the *_msgs object
|
||||
gets shut down.
|
||||
|
||||
*/
|
||||
|
||||
/* Public Opaque Handles */
|
||||
|
||||
/** A pointer to this is a opaque handle to a message handling facility */
|
||||
@ -85,13 +113,26 @@ struct libdax_msgs_item;
|
||||
|
||||
/* It is well advisable to let applications select severities via strings and
|
||||
forwarded functions libdax_msgs__text_to_sev(), libdax_msgs__sev_to_text().
|
||||
These macros are for use by libdax/libburn only.
|
||||
These macros are for use by the owner of libdax_msgs.
|
||||
*/
|
||||
|
||||
/** Use this to get messages of any severity. Do not use for submitting.
|
||||
*/
|
||||
#define LIBDAX_MSGS_SEV_ALL 0x00000000
|
||||
|
||||
|
||||
/** Messages of this severity shall transport plain disk file paths
|
||||
whenever an event of severity SORRY or above is related with an
|
||||
individual disk file.
|
||||
No message text shall be added to the file path. The ERRFILE message
|
||||
shall be issued before the human readable message which carries the
|
||||
true event severity. That message should contain the file path so it
|
||||
can be found by strstr(message, path)!=NULL.
|
||||
The error code shall be the same as with the human readable message.
|
||||
*/
|
||||
#define LIBDAX_MSGS_SEV_ERRFILE 0x08000000
|
||||
|
||||
|
||||
/** Debugging messages not to be visible to normal users by default
|
||||
*/
|
||||
#define LIBDAX_MSGS_SEV_DEBUG 0x10000000
|
||||
@ -112,15 +153,70 @@ struct libdax_msgs_item;
|
||||
*/
|
||||
#define LIBDAX_MSGS_SEV_WARNING 0x50000000
|
||||
|
||||
/** Non-fatal error messages indicating that parts of the action failed
|
||||
but processing will/should go on
|
||||
|
||||
/** Non-fatal error messages indicating that parts of an action failed but
|
||||
processing may go on if one accepts deviations from the desired result.
|
||||
|
||||
SORRY may also be the severity for incidents which are severe enough
|
||||
for FAILURE but happen within already started irrevocable actions,
|
||||
like ISO image generation. A precondition for such a severity ease is
|
||||
that the action can be continued after the incident.
|
||||
See below MISHAP for what xorriso would need instead of this kind of SORRY
|
||||
and generates for itself in case of libisofs image generation.
|
||||
|
||||
E.g.: A pattern yields no result.
|
||||
A speed setting cannot be made.
|
||||
A libisofs input file is inaccessible during image generation.
|
||||
|
||||
After SORRY a function should try to go on if that makes any sense
|
||||
and if no threshold prescribes abort on SORRY. The function should
|
||||
nevertheless indicate some failure in its return value.
|
||||
It should - but it does not have to.
|
||||
*/
|
||||
#define LIBDAX_MSGS_SEV_SORRY 0x60000000
|
||||
|
||||
/** An error message which puts the whole operation of libdax in question
|
||||
|
||||
/** A FAILURE (see below) which can be tolerated during long lasting
|
||||
operations just because they cannot simply be stopped or revoked.
|
||||
|
||||
xorriso converts libisofs SORRY messages issued during image generation
|
||||
into MISHAP messages in order to allow its evaluators to distinguish
|
||||
image generation problems from minor image composition problems.
|
||||
E.g.:
|
||||
A libisofs input file is inaccessible during image generation.
|
||||
|
||||
After a MISHAP a function should behave like after SORRY.
|
||||
*/
|
||||
#define LIBDAX_MSGS_SEV_MISHAP 0x64000000
|
||||
|
||||
|
||||
/** Non-fatal error indicating that an important part of an action failed and
|
||||
that only a new setup of preconditions will give hope for sufficient
|
||||
success.
|
||||
|
||||
E.g.: No media is inserted in the output drive.
|
||||
No write mode can be found for inserted media.
|
||||
A libisofs input file is inaccessible during grafting.
|
||||
|
||||
After FAILURE a function should end with a return value indicating failure.
|
||||
It is at the discretion of the function whether it ends immediately in any
|
||||
case or whether it tries to go on if the eventual threshold allows.
|
||||
*/
|
||||
#define LIBDAX_MSGS_SEV_FAILURE 0x68000000
|
||||
|
||||
|
||||
/** An error message which puts the whole operation of the program in question
|
||||
|
||||
E.g.: Not enough memory for essential temporary objects.
|
||||
Irregular errors from resources.
|
||||
Programming errors (soft assert).
|
||||
|
||||
After FATAL a function should end very soon with a return value
|
||||
indicating severe failure.
|
||||
*/
|
||||
#define LIBDAX_MSGS_SEV_FATAL 0x70000000
|
||||
|
||||
|
||||
/** A message from an abort handler which will finally finish libburn
|
||||
*/
|
||||
#define LIBDAX_MSGS_SEV_ABORT 0x71000000
|
||||
@ -133,7 +229,7 @@ struct libdax_msgs_item;
|
||||
|
||||
/* Registered Priorities */
|
||||
|
||||
/* Priorities are to be used by libburn/libdax only. */
|
||||
/* Priorities are to be selected by the programmers and not by the user. */
|
||||
|
||||
#define LIBDAX_MSGS_PRIO_ZERO 0x00000000
|
||||
#define LIBDAX_MSGS_PRIO_LOW 0x10000000
|
||||
@ -145,12 +241,23 @@ struct libdax_msgs_item;
|
||||
#define LIBDAX_MSGS_PRIO_NEVER 0x7fffffff
|
||||
|
||||
|
||||
/* Origin numbers of libburn drives may range from 0 to 1048575 */
|
||||
#define LIBDAX_MSGS_ORIGIN_DRIVE_BASE 0
|
||||
#define LIBDAX_MSGS_ORIGIN_DRIVE_TOP 0xfffff
|
||||
|
||||
/* Origin numbers of libisofs images may range from 1048575 to 2097152 */
|
||||
#define LIBDAX_MSGS_ORIGIN_IMAGE_BASE 0x100000
|
||||
#define LIBDAX_MSGS_ORIGIN_IMAGE_TOP 0x1fffff
|
||||
|
||||
|
||||
|
||||
/* Public Functions */
|
||||
|
||||
/* Calls initiated from inside libdax/libburn */
|
||||
/* Calls initiated from inside the direct owner (e.g. from libburn) */
|
||||
|
||||
|
||||
/** Create new empty message handling facility with queue.
|
||||
/** Create new empty message handling facility with queue and issue a first
|
||||
official reference to it.
|
||||
@param flag Bitfield for control purposes (unused yet, submit 0)
|
||||
@return >0 success, <=0 failure
|
||||
*/
|
||||
@ -159,18 +266,37 @@ int libdax_msgs_new(struct libdax_msgs **m, int flag);
|
||||
|
||||
/** Destroy a message handling facility and all its eventual messages.
|
||||
The submitted pointer gets set to NULL.
|
||||
Actually only the last destroy call of all offical references to the object
|
||||
will really dispose it. All others just decrement the reference counter.
|
||||
Call this function only with official reference pointers obtained by
|
||||
libdax_msgs_new() or libdax_msgs_refer(), and only once per such pointer.
|
||||
@param flag Bitfield for control purposes (unused yet, submit 0)
|
||||
@return 1 for success, 0 for pointer to NULL
|
||||
@return 1 for success, 0 for pointer to NULL, -1 for fatal error
|
||||
*/
|
||||
int libdax_msgs_destroy(struct libdax_msgs **m, int flag);
|
||||
|
||||
|
||||
/** Create an official reference to an existing libdax_msgs object. The
|
||||
references keep the object alive at least until it is released by
|
||||
a matching number of destroy calls. So each reference MUST be revoked
|
||||
by exactly one call to libdax_msgs_destroy().
|
||||
@param pt The pointer to be set and registered
|
||||
@param m A pointer to the existing object
|
||||
@param flag Bitfield for control purposes (unused yet, submit 0)
|
||||
@return 1 for success, 0 for failure
|
||||
*/
|
||||
int libdax_msgs_refer(struct libdax_msgs **pt, struct libdax_msgs *o, int flag);
|
||||
|
||||
|
||||
/** Submit a message to a message handling facility.
|
||||
@param driveno libdax drive number. Use -1 if no number is known.
|
||||
@param origin program specific identification number of the originator of
|
||||
a message. E.g. drive number. Programs should have an own
|
||||
range of origin numbers. See above LIBDAX_MSGS_ORIGIN_*_BASE
|
||||
Use -1 if no number is known.
|
||||
@param error_code Unique error code. Use only registered codes. See below.
|
||||
The same unique error_code may be issued at different
|
||||
occasions but those should be equivalent out of the view
|
||||
of a libdax application. (E.g. "cannot open ATA drive"
|
||||
of a libdax_msgs application. (E.g. "cannot open ATA drive"
|
||||
versus "cannot open SCSI drive" would be equivalent.)
|
||||
@param severity The LIBDAX_MSGS_SEV_* of the event.
|
||||
@param priority The LIBDAX_MSGS_PRIO_* number of the event.
|
||||
@ -179,12 +305,13 @@ int libdax_msgs_destroy(struct libdax_msgs **m, int flag);
|
||||
@param flag Bitfield for control purposes (unused yet, submit 0)
|
||||
@return 1 on success, 0 on rejection, <0 for severe errors
|
||||
*/
|
||||
int libdax_msgs_submit(struct libdax_msgs *m, int driveno, int error_code,
|
||||
int libdax_msgs_submit(struct libdax_msgs *m, int origin, int error_code,
|
||||
int severity, int priority, char *msg_text,
|
||||
int os_errno, int flag);
|
||||
|
||||
|
||||
/* Calls from applications (to be forwarded by libdax/libburn) */
|
||||
|
||||
/* Calls from applications (to be forwarded by direct owner) */
|
||||
|
||||
|
||||
/** Convert a registered severity number into a severity name
|
||||
@ -255,7 +382,7 @@ int libdax_msgs_item_get_msg(struct libdax_msgs_item *item,
|
||||
@return 1 on success, 0 on invalid item, <0 for servere errors
|
||||
*/
|
||||
int libdax_msgs_item_get_origin(struct libdax_msgs_item *item,
|
||||
double *timestamp, pid_t *process_id, int *driveno,
|
||||
double *timestamp, pid_t *process_id, int *origin,
|
||||
int flag);
|
||||
|
||||
|
||||
@ -268,14 +395,14 @@ int libdax_msgs_item_get_rank(struct libdax_msgs_item *item,
|
||||
int *severity, int *priority, int flag);
|
||||
|
||||
|
||||
#ifdef LIDBAX_MSGS_________________
|
||||
#ifdef LIBDAX_MSGS_________________
|
||||
|
||||
|
||||
/* Registered Error Codes */
|
||||
|
||||
|
||||
Format: error_code (LIBDAX_MSGS_SEV_*,LIBDAX_MSGS_PRIO_*) = explanation
|
||||
If no severity or priority are fixely associates, use "(,)".
|
||||
If no severity or priority are fixely associated, use "(,)".
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Range "libdax_msgs" : 0x00000000 to 0x0000ffff
|
||||
@ -283,6 +410,7 @@ Range "libdax_msgs" : 0x00000000 to 0x0000ffff
|
||||
0x00000000 (ALL,ZERO) = Initial setting in new libdax_msgs_item
|
||||
0x00000001 (DEBUG,ZERO) = Test error message
|
||||
0x00000002 (DEBUG,ZERO) = Debugging message
|
||||
0x00000003 (FATAL,HIGH) = Out of virtual memory
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
@ -299,11 +427,17 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
|
||||
0x00020002 (SORRY,HIGH) = Encountered error when closing drive
|
||||
0x00020003 (SORRY,HIGH) = Could not grab drive
|
||||
0x00020004 (NOTE,HIGH) = Opened O_EXCL scsi sibling
|
||||
0x00020005 (FATAL,HIGH) = Failed to open device
|
||||
0x00020005 (SORRY,HIGH) = Failed to open device
|
||||
0x00020006 (FATAL,HIGH) = Too many scsi siblings
|
||||
0x00020007 (NOTE,HIGH) = Closed O_EXCL scsi siblings
|
||||
0x00020008 (SORRY,HIGH) = Device busy. Failed to fcntl-lock
|
||||
0x00020009 (SORRY,HIGH) = Neither stdio-path nor its directory exist
|
||||
0x0002000a (FAILURE,HIGH) = Cannot accept '...' as SG_IO CDROM drive
|
||||
0x0002000b (FAILURE,HIGH) = File object '...' not found
|
||||
0x0002000c (FAILURE,HIGH) = Cannot start device file enumeration
|
||||
0x0002000d (FAILURE,HIGH) = Cannot enumerate next device
|
||||
|
||||
From the hunt on Assert:
|
||||
General library operations:
|
||||
|
||||
0x00020101 (WARNING,HIGH) = Cannot find given worker item
|
||||
0x00020102 (SORRY,HIGH) = A drive operation is still going on
|
||||
@ -311,7 +445,7 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
|
||||
0x00020104 (SORRY,HIGH) = NULL pointer caught
|
||||
0x00020105 (SORRY,HIGH) = Drive is already released
|
||||
0x00020106 (SORRY,HIGH) = Drive is busy on attempt to close
|
||||
0x00020107 (SORRY,HIGH) = Drive is busy on attempt to shut down library
|
||||
0x00020107 (WARNING,HIGH) = A drive is still busy on shutdown of library
|
||||
0x00020108 (SORRY,HIGH) = Drive is not grabbed on disc status inquiry
|
||||
0x00020108 (FATAL,HIGH) = Could not allocate new drive object
|
||||
0x00020109 (FATAL,HIGH) = Library not running
|
||||
@ -320,7 +454,7 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
|
||||
0x0002010c (FATAL,HIGH) = Failed to transfer command to drive
|
||||
0x0002010d (DEBUG,HIGH) = Could not inquire TOC
|
||||
0x0002010e (FATAL,HIGH) = Attempt to read ATIP from ungrabbed drive
|
||||
0x0002010f
|
||||
0x0002010f (DEBUG,HIGH) = SCSI error condition on command
|
||||
0x00020110 (FATAL,HIGH) = Persistent drive address too long
|
||||
0x00020111 (FATAL,HIGH) = Could not allocate new auxiliary object
|
||||
0x00020112 (SORRY,HIGH) = Bad combination of write_type and block_type
|
||||
@ -329,16 +463,238 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
|
||||
0x00020115 (SORRY,HIGH) = Attempt to set track mode to unusable value
|
||||
0x00020116 (FATAL,HIGH) = Track mode has unusable value
|
||||
0x00020117 (FATAL,HIGH) = toc_entry of drive is already in use
|
||||
0x00020118 (DEBUG,HIGH) = Closing track
|
||||
0x00020119 (DEBUG,HIGH) = Closing session
|
||||
0x0002011a (NOTE,HIGH) = Padding up track to minimum size
|
||||
0x0002011b (FATAL,HIGH) = Attempt to read track info from ungrabbed drive
|
||||
0x0002011c (FATAL,HIGH) = Attempt to read track info from busy drive
|
||||
0x0002011d (FATAL,HIGH) = SCSI error on write
|
||||
0x0002011e (SORRY,HIGH) = Unsuitable media detected
|
||||
0x0002011f (SORRY,HIGH) = Burning is restricted to a single track
|
||||
0x00020120 (NOTE,HIGH) = FORMAT UNIT ignored
|
||||
0x00020121 (FATAL,HIGH) = Write preparation setup failed
|
||||
0x00020122 (FATAL,HIGH) = SCSI error on format_unit
|
||||
0x00020123 (SORRY,HIGH) = DVD Media are unsuitable for desired track type
|
||||
0x00020124 (SORRY,HIGH) = SCSI error on set_streaming
|
||||
0x00020125 (SORRY,HIGH) = Write start address not supported
|
||||
0x00020126 (SORRY,HIGH) = Write start address not properly aligned
|
||||
0x00020127 (NOTE,HIGH) = Write start address is ...
|
||||
0x00020128 (FATAL,HIGH) = Unsupported inquiry_type with mmc_get_performance
|
||||
0x00020129 (SORRY,HIGH) = Will not format media type
|
||||
0x0002012a (FATAL,HIGH) = Cannot inquire write mode capabilities
|
||||
0x0002012b (FATAL,HIGH) = Drive offers no suitable write mode with this job
|
||||
0x0002012c (SORRY,HIGH) = Too many logical tracks recorded
|
||||
0x0002012d (FATAL,HIGH) = Exceeding range of permissible write addresses
|
||||
0x0002012e (NOTE,HIGH) = Activated track default size
|
||||
0x0002012f (SORRY,HIGH) = SAO is restricted to single fixed size session
|
||||
0x00020130 (SORRY,HIGH) = Drive and media state unsuitable for blanking
|
||||
0x00020131 (SORRY,HIGH) = No suitable formatting type offered by drive
|
||||
0x00020132 (SORRY,HIGH) = Selected format is not suitable for libburn
|
||||
0x00020133 (SORRY,HIGH) = Cannot mix data and audio in SAO mode
|
||||
0x00020134 (NOTE,HIGH) = Defaulted TAO to DAO
|
||||
0x00020135 (SORRY,HIGH) = Cannot perform TAO, job unsuitable for DAO
|
||||
0x00020136 (SORRY,HIGH) = DAO burning restricted to single fixed size track
|
||||
0x00020137 (HINT,HIGH) = TAO would be possible
|
||||
0x00020138 (FATAL,HIGH) = Cannot reserve track
|
||||
0x00020139 (SORRY,HIGH) = Write job parameters are unsuitable
|
||||
0x0002013a (FATAL,HIGH) = No suitable media detected
|
||||
0x0002013b (DEBUG,HIGH) = SCSI command indicates host or driver error
|
||||
0x0002013c (SORRY,HIGH) = Malformed capabilities page 2Ah received
|
||||
0x0002013d (DEBUG,LOW) = Waiting for free buffer space takes long time
|
||||
0x0002013e (SORRY,HIGH) = Timeout with waiting for free buffer. Now disabled
|
||||
0x0002013f (DEBUG,LOW) = Reporting total time spent with waiting for buffer
|
||||
0x00020140 (FATAL,HIGH) = Drive is busy on attempt to write random access
|
||||
0x00020141 (SORRY,HIGH) = Write data count not properly aligned
|
||||
0x00020142 (FATAL,HIGH) = Drive is not grabbed on random access write
|
||||
0x00020143 (SORRY,HIGH) = Read start address not properly aligned
|
||||
0x00020144 (SORRY,HIGH) = SCSI error on read
|
||||
0x00020145 (FATAL,HIGH) = Drive is busy on attempt to read data
|
||||
0x00020146 (FATAL,HIGH) = Drive is a virtual placeholder
|
||||
0x00020147 (SORRY,HIGH) = Cannot address start byte
|
||||
0x00020148 (SORRY,HIGH) = Cannot write desired amount of data
|
||||
0x00020149 (SORRY,HIGH) = Unsuitable filetype for pseudo-drive
|
||||
0x0002014a (SORRY,HIGH) = Cannot read desired amount of data
|
||||
0x0002014b (SORRY,HIGH) = Drive is already registered resp. scanned
|
||||
0x0002014c (FATAL,HIGH) = Emulated drive caught in SCSI function
|
||||
0x0002014d (SORRY,HIGH) = Asynchromous SCSI error
|
||||
0x0002014f (SORRY,HIGH) = Timeout with asynchromous SCSI command
|
||||
0x00020150 (DEBUG,LOW) = Reporting asynchronous waiting time
|
||||
0x00020151 (FAILURE,HIGH) = Read attempt on write-only drive
|
||||
0x00020152 (FATAL,HIGH) = Cannot start fifo thread
|
||||
0x00020153 (SORRY,HIGH) = Read error on fifo input
|
||||
0x00020154 (NOTE,HIGH) = Forwarded input error ends output
|
||||
0x00020155 (SORRY,HIGH) = Desired fifo buffer too large
|
||||
0x00020156 (SORRY,HIGH) = Desired fifo buffer too small
|
||||
0x00020157 (FATAL,HIGH) = burn_source is not a fifo object
|
||||
0x00020158 (DEBUG,LOW) = Reporting thread disposal precautions
|
||||
0x00020159 (DEBUG,HIGH) = TOC Format 0 returns inconsistent data
|
||||
0x0002015a (NOTE,HIGH) = Could not examine busy device
|
||||
0x0002015b (HINT,HIGH) = Busy '...' seems to be a hard disk, as '...1' exists
|
||||
0x0002015c (FAILURE,HIGH) = Fifo size too small for desired peek buffer
|
||||
0x0002015d (FAILURE,HIGH) = Fifo input ended short of desired peek buffer size
|
||||
0x0002015e (FATAL,HIGH) = Fifo is already under consumption when peeking
|
||||
0x0002015f (MISHAP,HIGH) = Damaged CD table-of-content detected and truncated
|
||||
0x00020160 (WARNING,HIGH) = Session without leadout encountered
|
||||
0x00020161 (WARNING,HIGH) = Empty session deleted
|
||||
0x00020162 (SORRY,HIGH) = BD-R not unformatted blank any more. Cannot format
|
||||
0x00020163 (NOTE,HIGH) = Blank BD-R left unformatted for zero spare capacity
|
||||
0x00020164 (SORRY,HIGH) = Drive does not format BD-RE without spares
|
||||
0x00020165 (WARNING,HIGH) = Drive does not support fast formatting
|
||||
0x00020166 (WARNING,HIGH) = Drive does not support full formatting
|
||||
0x00020167 (SORRY,HIGH) = Drive does not support non-default formatting
|
||||
0x00020168 (FAILURE,HIGH) = Media not properly formatted. Cannot write.
|
||||
0x00020169 (WARNING,HIGH) = Last session on media is still open
|
||||
0x0002016a (FAILURE,HIGH) = No MMC transport adapter is present
|
||||
0x0002016b (WARNING,HIGH) = No MMC transport adapter is present
|
||||
0x0002016c (DEBUG,HIGH) = No MMC transport adapter is present
|
||||
0x0002016e (DEBUG,HIGH) = MODE SENSE page 2A too short
|
||||
0x0002016f (DEBUG,HIGH) = Unable to grab scanned drive
|
||||
0x00020170 (NOTE,HIGH) = Closing open session before writing new one
|
||||
0x00020171 (NOTE,HIGH) = Closing BD-R with accidently open session
|
||||
0x00020172 (SORRY,HIGH) = Read start address larger than number of readable blocks
|
||||
0x00020173 (FAILURE,HIGH) = Drive tells NWA smaller than last written address
|
||||
0x00020174 (SORRY,HIGH) = Fifo alignment does not allow desired read size
|
||||
0x00020175 (FATAL,HIGH) = Supporting library is too old
|
||||
0x00020176 (NOTE,HIGH) = Stream recording disabled because of small OS buffer
|
||||
0x00020177 (ABORT,HIGH) = Urged drive worker threads to do emergency halt
|
||||
0x00020178 (DEBUG,HIGH) = Write thread ended
|
||||
0x00020179 (FAILURE,HIGH) = Offset source start address is before end of previous source
|
||||
0x0002017a (FAILURE,HIGH) = Expected offset source object as parameter
|
||||
0x0002017b (WARNING,HIGH) = Sequential BD-R media likely to soon fail writing
|
||||
0x0002017c (FAILURE,HIGH) = No valid write type selected
|
||||
0x0002017d (FATAL,HIGH) = Invalid file descriptor with stdio pseudo-drive
|
||||
0x0002017e (FAILURE,HIGH) = Failed to close track, session, or disc
|
||||
0x0002017f (FAILURE,HIGH) = Failed to synchronize drive cache
|
||||
0x00020180 (FAILURE,HIGH) = Premature end of input encountered
|
||||
0x00020181 (FAILURE,HIGH) = Pseudo-drive is a read-only file. Cannot write.
|
||||
0x00020182 (FAILURE,HIGH) = Cannot truncate disk file for pseudo blanking
|
||||
0x00020183 (WARNING,HIGH) = Failed to open device (a pseudo-drive) for reading
|
||||
0x00020184 (WARNING,HIGH) = No Next-Writable-Address
|
||||
0x00020185 (WARNING,HIGH) = Track damaged, not closed and not writable
|
||||
0x00020186 (WARNING,HIGH) = Track damaged and not closed
|
||||
0x00020187 (NOTE,HIGH) = Track not marked as damaged. No action taken.
|
||||
0x00020188 (FAILURE,HIGH) = Cannot close damaged track on given media type
|
||||
|
||||
libdax_audioxtr:
|
||||
0x00020200 (SORRY,HIGH) = Cannot open audio source file
|
||||
0x00020201 (SORRY,HIGH) = Audio source file has unsuitable format
|
||||
0x00020202 (SORRY,HIGH) = Failed to prepare reading of audio data
|
||||
|
||||
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Range "vreixo" : 0x00030000 to 0x0003ffff
|
||||
|
||||
0x0003ffff (FAILURE,HIGH) = Operation canceled
|
||||
0x0003fffe (FATAL,HIGH) = Unknown or unexpected fatal error
|
||||
0x0003fffd (FAILURE,HIGH) = Unknown or unexpected error
|
||||
0x0003fffc (FATAL,HIGH) = Internal programming error
|
||||
0x0003fffb (FAILURE,HIGH) = NULL pointer where NULL not allowed
|
||||
0x0003fffa (FATAL,HIGH) = Memory allocation error
|
||||
0x0003fff9 (FATAL,HIGH) = Interrupted by a signal
|
||||
0x0003fff8 (FAILURE,HIGH) = Invalid parameter value
|
||||
0x0003fff7 (FATAL,HIGH) = Cannot create a needed thread
|
||||
0x0003fff6 (FAILURE,HIGH) = Write error
|
||||
0x0003fff5 (FAILURE,HIGH) = Buffer read error
|
||||
0x0003ffc0 (FAILURE,HIGH) = Trying to add a node already added to another dir
|
||||
0x0003ffbf (FAILURE,HIGH) = Node with same name already exist
|
||||
0x0003ffbe (FAILURE,HIGH) = Trying to remove a node that was not added to dir
|
||||
0x0003ffbd (FAILURE,HIGH) = A requested node does not exist
|
||||
0x0003ffbc (FAILURE,HIGH) = Image already bootable
|
||||
0x0003ffbb (FAILURE,HIGH) = Trying to use an invalid file as boot image
|
||||
0x0003ff80 (FAILURE,HIGH) = Error on file operation
|
||||
0x0003ff7f (FAILURE,HIGH) = Trying to open an already openned file
|
||||
0x0003ff7e (FAILURE,HIGH) = Access to file is not allowed
|
||||
0x0003ff7d (FAILURE,HIGH) = Incorrect path to file
|
||||
0x0003ff7c (FAILURE,HIGH) = The file does not exist in the filesystem
|
||||
0x0003ff7b (FAILURE,HIGH) = Trying to read or close a file not openned
|
||||
0x0003ff7a (FAILURE,HIGH) = Directory used where no dir is expected
|
||||
0x0003ff79 (FAILURE,HIGH) = File read error
|
||||
0x0003ff78 (FAILURE,HIGH) = Not dir used where a dir is expected
|
||||
0x0003ff77 (FAILURE,HIGH) = Not symlink used where a symlink is expected
|
||||
0x0003ff76 (FAILURE,HIGH) = Cannot seek to specified location
|
||||
0x0003ff75 (HINT,MEDIUM) = File not supported in ECMA-119 tree and ignored
|
||||
0x0003ff74 (HINT,MEDIUM) = File bigger than supported by used standard
|
||||
0x0003ff73 (MISHAP,HIGH) = File read error during image creation
|
||||
0x0003ff72 (HINT,MEDIUM) = Cannot convert filename to requested charset
|
||||
0x0003ff71 (SORRY,HIGH) = File cannot be added to the tree
|
||||
0x0003ff70 (HINT,MEDIUM) = File path breaks specification constraints
|
||||
0x0003ff00 (FAILURE,HIGH) = Charset conversion error
|
||||
0x0003feff (FAILURE,HIGH) = Too much files to mangle
|
||||
0x0003fec0 (FAILURE,HIGH) = Wrong or damaged Primary Volume Descriptor
|
||||
0x0003febf (SORRY,HIGH) = Wrong or damaged RR entry
|
||||
0x0003febe (SORRY,HIGH) = Unsupported RR feature
|
||||
0x0003febd (FAILURE,HIGH) = Wrong or damaged ECMA-119
|
||||
0x0003febc (FAILURE,HIGH) = Unsupported ECMA-119 feature
|
||||
0x0003febb (SORRY,HIGH) = Wrong or damaged El-Torito catalog
|
||||
0x0003feba (SORRY,HIGH) = Unsupported El-Torito feature
|
||||
0x0003feb9 (SORRY,HIGH) = Cannot patch isolinux boot image
|
||||
0x0003feb8 (SORRY,HIGH) = Unsupported SUSP feature
|
||||
0x0003feb7 (WARNING,HIGH) = Error on a RR entry that can be ignored
|
||||
0x0003feb6 (HINT,MEDIUM) = Error on a RR entry that can be ignored
|
||||
0x0003feb5 (WARNING,HIGH) = Multiple ER SUSP entries found
|
||||
0x0003feb4 (HINT,MEDIUM) = Unsupported volume descriptor found
|
||||
0x0003feb3 (WARNING,HIGH) = El-Torito related warning
|
||||
0x0003feb2 (MISHAP,HIGH) = Image write cancelled
|
||||
0x0003feb1 (WARNING,HIGH) = El-Torito image is hidden
|
||||
|
||||
Outdated codes which may not be re-used for other purposes than
|
||||
re-instating them, if ever:
|
||||
|
||||
X 0x00031001 (SORRY,HIGH) = Cannot read file (ignored)
|
||||
X 0x00031002 (FATAL,HIGH) = Cannot read file (operation canceled)
|
||||
X 0x00031000 (FATAL,HIGH) = Unsupported ISO-9660 image
|
||||
X 0x00031001 (HINT,MEDIUM) = Unsupported Vol Desc that will be ignored
|
||||
X 0x00031002 (FATAL,HIGH) = Damaged ISO-9660 image
|
||||
X 0x00031003 (SORRY,HIGH) = Cannot read previous image file
|
||||
X 0x00030101 (HINT,MEDIUM) = Unsupported SUSP entry that will be ignored
|
||||
X 0x00030102 (SORRY,HIGH) = Wrong/damaged SUSP entry
|
||||
X 0x00030103 (WARNING,MEDIUM)= Multiple SUSP ER entries where found
|
||||
X 0x00030111 (SORRY,HIGH) = Unsupported RR feature
|
||||
X 0x00030112 (SORRY,HIGH) = Error in a Rock Ridge entry
|
||||
X 0x00030201 (HINT,MEDIUM) = Unsupported Boot Vol Desc that will be ignored
|
||||
X 0x00030202 (SORRY,HIGH) = Wrong El-Torito catalog
|
||||
X 0x00030203 (HINT,MEDIUM) = Unsupported El-Torito feature
|
||||
X 0x00030204 (SORRY,HIGH) = Invalid file to be an El-Torito image
|
||||
X 0x00030205 (WARNING,MEDIUM)= Cannot properly patch isolinux image
|
||||
X 0x00030206 (WARNING,MEDIUM)= Copying El-Torito from a previous image without
|
||||
X enought info about it
|
||||
X 0x00030301 (NOTE,MEDIUM) = Unsupported file type for Joliet tree
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Range "application" : 0x00040000 to 0x0004ffff
|
||||
|
||||
0x00040000 (ABORT,HIGH) : Application supplied message
|
||||
0x00040001 (FATAL,HIGH) : Application supplied message
|
||||
0x00040002 (SORRY,HIGH) : Application supplied message
|
||||
0x00040003 (WARNING,HIGH) : Application supplied message
|
||||
0x00040004 (HINT,HIGH) : Application supplied message
|
||||
0x00040005 (NOTE,HIGH) : Application supplied message
|
||||
0x00040006 (UPDATE,HIGH) : Application supplied message
|
||||
0x00040007 (DEBUG,HIGH) : Application supplied message
|
||||
0x00040008 (*,HIGH) : Application supplied message
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Range "libisofs-xorriso" : 0x00050000 to 0x0005ffff
|
||||
|
||||
This is an alternative representation of libisofs.so.6 error codes in xorriso.
|
||||
If values returned by iso_error_get_code() do not fit into 0x30000 to 0x3ffff
|
||||
then they get truncated to 16 bit and mapped into this range.
|
||||
(This should never need to happen, of course.)
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
Range "libisoburn" : 0x00060000 to 0x00006ffff
|
||||
|
||||
0x00060000 (*,*) : Message which shall be attributed to libisoburn
|
||||
|
||||
>>> the messages of libisoburn need to be registered individually
|
||||
|
||||
|
||||
------------------------------------------------------------------------------
|
||||
|
||||
#endif /* LIDBAX_MSGS_________________ */
|
||||
#endif /* LIBDAX_MSGS_________________ */
|
||||
|
||||
|
||||
|
||||
|
37
libburn/libdax_msgs_to_xyz_msgs.sh
Executable file
37
libburn/libdax_msgs_to_xyz_msgs.sh
Executable 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
|
||||
|
4355
libburn/mmc.c
4355
libburn/mmc.c
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,11 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __MMC
|
||||
#define __MMC
|
||||
|
||||
@ -37,7 +43,11 @@ void mmc_set_speed(struct burn_drive *, int, int);
|
||||
void mmc_read_lead_in(struct burn_drive *, struct buffer *);
|
||||
void mmc_perform_opc(struct burn_drive *);
|
||||
void mmc_get_configuration(struct burn_drive *);
|
||||
int mmc_get_nwa(struct burn_drive *);
|
||||
|
||||
/* ts A61110 : added parameters trackno, lba, nwa. Redefined return value.
|
||||
@return 1=nwa is valid , 0=nwa is not valid , -1=error */
|
||||
int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa);
|
||||
|
||||
void mmc_send_cue_sheet(struct burn_drive *, struct cue_sheet *);
|
||||
|
||||
/* ts A61023 : get size and free space of drive buffer */
|
||||
@ -47,4 +57,57 @@ int mmc_read_buffer_capacity(struct burn_drive *d);
|
||||
*/
|
||||
int mmc_setup_drive(struct burn_drive *d);
|
||||
|
||||
/* ts A61219 : learned much from dvd+rw-tools-7.0: plus_rw_format()
|
||||
and mmc5r03c.pdf, 6.5 FORMAT UNIT */
|
||||
int mmc_format_unit(struct burn_drive *d, off_t size, int flag);
|
||||
|
||||
/* ts A61225 : obtain write speed descriptors via ACh GET PERFORMANCE */
|
||||
int mmc_get_write_performance(struct burn_drive *d);
|
||||
|
||||
|
||||
/* ts A61229 : outsourced from spc_select_write_params() */
|
||||
/* Note: Page data is not zeroed here to allow preset defaults. Thus
|
||||
memset(pd, 0, 2 + d->mdata->write_page_length);
|
||||
is the eventual duty of the caller.
|
||||
*/
|
||||
int mmc_compose_mode_page_5(struct burn_drive *d,
|
||||
const struct burn_write_opts *o,
|
||||
unsigned char *pd);
|
||||
|
||||
/* ts A70201 */
|
||||
int mmc_four_char_to_int(unsigned char *data);
|
||||
|
||||
/* ts A70812 : return 0 = ok , return BE_CANCELLED = error occured */
|
||||
int mmc_read_10(struct burn_drive *d, int start, int amount,
|
||||
struct buffer *buf);
|
||||
|
||||
/* ts A81210 : Determine the upper limit of readable data size */
|
||||
int mmc_read_capacity(struct burn_drive *d);
|
||||
|
||||
/* ts A61201 */
|
||||
char *mmc_obtain_profile_name(int profile_number);
|
||||
|
||||
|
||||
/* mmc5r03c.pdf 4.3.4.4.1 d) "The maximum number of RZones is 2 302." */
|
||||
#define BURN_MMC_FAKE_TOC_MAX_SIZE 2302
|
||||
|
||||
|
||||
/* ts A90903 */
|
||||
/* MMC backend of API call burn_get_media_product_id()
|
||||
*/
|
||||
int mmc_get_media_product_id(struct burn_drive *d,
|
||||
char **product_id, char **media_code1, char **media_code2,
|
||||
char **book_type, int flag);
|
||||
|
||||
|
||||
/* ts A60910 (estimated) */
|
||||
int mmc_function_spy(struct burn_drive *d, char * text);
|
||||
|
||||
/* ts A91118 */
|
||||
int mmc_start_if_needed(struct burn_drive *d, int flag);
|
||||
|
||||
/* ts B00924 */
|
||||
int mmc_get_bd_spare_info(struct burn_drive *d,
|
||||
int *alloc_blocks, int *free_blocks, int flag);
|
||||
|
||||
#endif /*__MMC*/
|
||||
|
@ -1,5 +1,14 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#include "null.h"
|
||||
#include "libburn.h"
|
||||
#include <stdlib.h>
|
||||
@ -15,12 +24,16 @@ struct burn_source *burn_null_source_new(void)
|
||||
{
|
||||
struct burn_source *src;
|
||||
|
||||
src = malloc(sizeof(struct burn_source));
|
||||
src = calloc(1, sizeof(struct burn_source));
|
||||
src->refcount = 1;
|
||||
src->read = null_read;
|
||||
src->read_sub = NULL;
|
||||
|
||||
src->get_size = 0;
|
||||
|
||||
/* ts A70126 */
|
||||
src->set_size = NULL;
|
||||
|
||||
src->free_data = NULL;
|
||||
src->data = NULL;
|
||||
return src;
|
||||
|
@ -1,5 +1,16 @@
|
||||
|
||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#include "libburn.h"
|
||||
#include "options.h"
|
||||
#include "drive.h"
|
||||
#include "transport.h"
|
||||
|
||||
/* ts A61007 */
|
||||
@ -16,7 +27,7 @@ struct burn_write_opts *burn_write_opts_new(struct burn_drive *drive)
|
||||
{
|
||||
struct burn_write_opts *opts;
|
||||
|
||||
opts = malloc(sizeof(struct burn_write_opts));
|
||||
opts = calloc(1, sizeof(struct burn_write_opts));
|
||||
if (opts == NULL) {
|
||||
libdax_msgs_submit(libdax_messenger, -1, 0x00020111,
|
||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
||||
@ -32,6 +43,14 @@ struct burn_write_opts *burn_write_opts_new(struct burn_drive *drive)
|
||||
opts->simulate = 0;
|
||||
opts->underrun_proof = drive->mdata->underrun_proof;
|
||||
opts->perform_opc = 1;
|
||||
opts->obs = -1;
|
||||
opts->obs_pad = 0;
|
||||
opts->start_byte = -1;
|
||||
opts->fill_up_media = 0;
|
||||
opts->force_is_set = 0;
|
||||
opts->do_stream_recording = 0;
|
||||
opts->dvd_obs_override = 0;
|
||||
opts->stdio_fsync_size = Libburn_stdio_fsync_limiT;
|
||||
opts->has_mediacatalog = 0;
|
||||
opts->format = BURN_CDROM;
|
||||
opts->multi = 0;
|
||||
@ -49,7 +68,7 @@ struct burn_read_opts *burn_read_opts_new(struct burn_drive *drive)
|
||||
{
|
||||
struct burn_read_opts *opts;
|
||||
|
||||
opts = malloc(sizeof(struct burn_read_opts));
|
||||
opts = calloc(1, sizeof(struct burn_read_opts));
|
||||
opts->drive = drive;
|
||||
opts->refcount = 1;
|
||||
opts->raw = 0;
|
||||
@ -106,7 +125,7 @@ void burn_write_opts_set_toc_entries(struct burn_write_opts *opts, int count,
|
||||
struct burn_toc_entry *toc_entries)
|
||||
{
|
||||
opts->toc_entries = count;
|
||||
opts->toc_entry = malloc(count * sizeof(struct burn_toc_entry));
|
||||
opts->toc_entry = calloc(count, sizeof(struct burn_toc_entry));
|
||||
memcpy(opts->toc_entry, &toc_entries,
|
||||
sizeof(struct burn_toc_entry) * count);
|
||||
}
|
||||
@ -118,16 +137,26 @@ void burn_write_opts_set_format(struct burn_write_opts *opts, int format)
|
||||
|
||||
int burn_write_opts_set_simulate(struct burn_write_opts *opts, int sim)
|
||||
{
|
||||
/* <<< ts A70529 :
|
||||
One cannot predict the ability to simulate from page 05h
|
||||
information alone. This check is now done later in
|
||||
function burn_write_opts_auto_write_type().
|
||||
|
||||
if (opts->drive->mdata->simulate) {
|
||||
opts->simulate = sim;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
*/
|
||||
opts->simulate = !!sim;
|
||||
return 1;
|
||||
}
|
||||
|
||||
int burn_write_opts_set_underrun_proof(struct burn_write_opts *opts,
|
||||
int underrun_proof)
|
||||
{
|
||||
if (opts->drive->mdata->valid <= 0)
|
||||
return 0;
|
||||
if (opts->drive->mdata->underrun_proof) {
|
||||
opts->underrun_proof = underrun_proof;
|
||||
return 1;
|
||||
@ -152,6 +181,254 @@ void burn_write_opts_set_mediacatalog(struct burn_write_opts *opts,
|
||||
memcpy(opts->mediacatalog, &mediacatalog, 13);
|
||||
}
|
||||
|
||||
|
||||
/* ts A61106 */
|
||||
void burn_write_opts_set_multi(struct burn_write_opts *opts, int multi)
|
||||
{
|
||||
opts->multi = !!multi;
|
||||
}
|
||||
|
||||
|
||||
/* ts A61222 */
|
||||
void burn_write_opts_set_start_byte(struct burn_write_opts *opts, off_t value)
|
||||
{
|
||||
opts->start_byte = value;
|
||||
}
|
||||
|
||||
|
||||
/* ts A70207 API */
|
||||
/** @param flag Bitfield for control purposes:
|
||||
bit0= do not choose type but check the one that is already set
|
||||
bit1= do not issue error messages via burn_msgs queue
|
||||
*/
|
||||
enum burn_write_types burn_write_opts_auto_write_type(
|
||||
struct burn_write_opts *opts, struct burn_disc *disc,
|
||||
char reasons[BURN_REASONS_LEN], int flag)
|
||||
{
|
||||
struct burn_multi_caps *caps = NULL;
|
||||
struct burn_drive *d = opts->drive;
|
||||
struct burn_disc_mode_demands demands;
|
||||
enum burn_write_types wt;
|
||||
int ret, would_do_sao = 0;
|
||||
char *reason_pt;
|
||||
|
||||
reasons[0] = 0;
|
||||
|
||||
if (d->status != BURN_DISC_BLANK &&
|
||||
d->status != BURN_DISC_APPENDABLE){
|
||||
if (d->status == BURN_DISC_FULL)
|
||||
strcat(reasons, "MEDIA: closed or not recordable, ");
|
||||
else
|
||||
strcat(reasons,"MEDIA: no writeable media detected, ");
|
||||
if (!(flag & 3))
|
||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||
0x0002013a,
|
||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"No suitable media detected", 0, 0);
|
||||
return BURN_WRITE_NONE;
|
||||
}
|
||||
ret = burn_disc_get_write_mode_demands(disc, opts, &demands,
|
||||
!!opts->fill_up_media);
|
||||
if (ret <= 0) {
|
||||
strcat(reasons, "cannot recognize job demands, ");
|
||||
{wt = BURN_WRITE_NONE; goto ex;}
|
||||
}
|
||||
if (demands.exotic_track && !d->current_is_cd_profile) {
|
||||
if (demands.audio)
|
||||
strcat(reasons, "audio track prohibited by non-CD, ");
|
||||
else
|
||||
strcat(reasons, "exotic track prohibited by non-CD, ");
|
||||
{wt = BURN_WRITE_NONE; goto ex;}
|
||||
}
|
||||
if ((flag & 1) && opts->write_type != BURN_WRITE_SAO)
|
||||
goto try_tao;
|
||||
reason_pt = reasons + strlen(reasons);
|
||||
strcat(reasons, "SAO: ");
|
||||
if (d->status != BURN_DISC_BLANK) {
|
||||
strcat(reasons, "write type SAO works only on blank media, ");
|
||||
goto try_tao;
|
||||
}
|
||||
burn_disc_free_multi_caps(&caps);
|
||||
ret = burn_disc_get_multi_caps(d, BURN_WRITE_SAO, &caps, 0);
|
||||
if (ret < 0) {
|
||||
no_caps:;
|
||||
strcat(reasons, "cannot inquire write mode capabilities, ");
|
||||
{wt = BURN_WRITE_NONE; goto ex;}
|
||||
} else if (ret == 0) {
|
||||
strcat(reasons, "no SAO offered by drive and media, ");
|
||||
goto no_sao;
|
||||
}
|
||||
if ((opts->multi || demands.multi_session) &&
|
||||
!caps->multi_session)
|
||||
strcat(reasons, "multi session capability lacking, ");
|
||||
if (demands.will_append)
|
||||
strcat(reasons, "appended session capability lacking, ");
|
||||
if (demands.multi_track && !caps->multi_track)
|
||||
strcat(reasons, "multi track capability lacking, ");
|
||||
if (demands.unknown_track_size == 1 &&
|
||||
(caps->might_do_sao == 1 || caps->might_do_sao == 3))
|
||||
strcat(reasons, "track size unpredictable, ");
|
||||
if (demands.mixed_mode)
|
||||
strcat(reasons, "tracks of different modes mixed, ");
|
||||
if (demands.exotic_track && !d->current_is_cd_profile)
|
||||
strcat(reasons, "non-data track on non-cd, ");
|
||||
else if (d->current_is_cd_profile)
|
||||
if ((d->block_types[BURN_WRITE_TAO] & demands.block_types) !=
|
||||
demands.block_types)
|
||||
strcat(reasons, "drive dislikes block type, ");
|
||||
if (d->current_is_cd_profile && opts->fill_up_media)
|
||||
strcat(reasons, "cd sao cannot do media fill up yet, ");
|
||||
if (strcmp(reason_pt, "SAO: ") != 0)
|
||||
goto no_sao;
|
||||
would_do_sao = 1;
|
||||
if (demands.unknown_track_size == 2 && (!(flag & 1)) &&
|
||||
(caps->might_do_sao == 1 || caps->might_do_sao == 3)) {
|
||||
strcat(reasons, "would have to use default track sizes, ");
|
||||
goto no_sao;
|
||||
} else if (caps->might_do_sao >= 3 && !(flag & 1))
|
||||
goto try_tao;
|
||||
do_sao:;
|
||||
if (caps->might_simulate == 0 && opts->simulate && !opts->force_is_set)
|
||||
goto no_simulate;
|
||||
if (!(flag & 1))
|
||||
burn_write_opts_set_write_type(
|
||||
opts, BURN_WRITE_SAO, BURN_BLOCK_SAO);
|
||||
{wt = BURN_WRITE_SAO; goto ex;}
|
||||
no_sao:;
|
||||
try_tao:;
|
||||
if ((flag & 1) && opts->write_type != BURN_WRITE_TAO)
|
||||
goto try_raw;
|
||||
reason_pt = reasons + strlen(reasons);
|
||||
strcat(reasons, "TAO: ");
|
||||
burn_disc_free_multi_caps(&caps);
|
||||
ret = burn_disc_get_multi_caps(d, BURN_WRITE_TAO, &caps, 0);
|
||||
if (ret < 0)
|
||||
goto no_caps;
|
||||
if (ret == 0) {
|
||||
strcat(reasons, "no TAO offered by drive and media, ");
|
||||
goto no_tao;
|
||||
}
|
||||
if ((opts->multi || demands.multi_session) && !caps->multi_session)
|
||||
strcat(reasons, "multi session capability lacking, ");
|
||||
if (demands.multi_track && !caps->multi_track)
|
||||
strcat(reasons, "multi track capability lacking, ");
|
||||
if (demands.exotic_track && !d->current_is_cd_profile)
|
||||
strcat(reasons, "non-data track on non-cd, ");
|
||||
if (d->current_is_cd_profile && !opts->force_is_set)
|
||||
if ((d->block_types[BURN_WRITE_TAO] & demands.block_types) !=
|
||||
demands.block_types)
|
||||
strcat(reasons, "drive dislikes block type, ");
|
||||
if (strcmp(reason_pt, "TAO: ") != 0)
|
||||
goto no_tao;
|
||||
/* ( TAO data/audio block size will be handled automatically ) */
|
||||
if (caps->might_simulate == 0 && opts->simulate && !opts->force_is_set)
|
||||
goto no_simulate;
|
||||
if (!(flag & 1))
|
||||
burn_write_opts_set_write_type(
|
||||
opts, BURN_WRITE_TAO, BURN_BLOCK_MODE1);
|
||||
{wt = BURN_WRITE_TAO; goto ex;}
|
||||
no_tao:;
|
||||
if (would_do_sao && !(flag & 1))
|
||||
goto do_sao;
|
||||
if (!d->current_is_cd_profile)
|
||||
goto no_write_mode;
|
||||
try_raw:;
|
||||
if ((flag & 1) && opts->write_type != BURN_WRITE_RAW)
|
||||
goto no_write_mode;
|
||||
|
||||
if (!(flag & 1)) /* For now: no automatic raw write modes */
|
||||
goto no_write_mode;
|
||||
|
||||
reason_pt = reasons + strlen(reasons);
|
||||
strcat(reasons, "RAW: ");
|
||||
if (!d->current_is_cd_profile)
|
||||
strcat(reasons, "write type RAW prohibited by non-cd, ");
|
||||
else if (d->status != BURN_DISC_BLANK)
|
||||
strcat(reasons, "write type RAW works only on blank media, ");
|
||||
else if ((d->block_types[BURN_WRITE_TAO] & demands.block_types) !=
|
||||
demands.block_types)
|
||||
strcat(reasons, "drive dislikes block type, ");
|
||||
if (strcmp(reason_pt, "RAW: ") != 0)
|
||||
goto no_write_mode;
|
||||
if (!opts->force_is_set)
|
||||
goto no_simulate;
|
||||
|
||||
/* For now: no setting of raw write modes */
|
||||
|
||||
{wt = BURN_WRITE_RAW; goto ex;}
|
||||
|
||||
no_write_mode:;
|
||||
{wt = BURN_WRITE_NONE; goto ex;}
|
||||
|
||||
no_simulate:;
|
||||
strcat(reasons,
|
||||
"simulation of write job not supported by drive and media, ");
|
||||
{wt = BURN_WRITE_NONE; goto ex;}
|
||||
|
||||
ex:;
|
||||
burn_disc_free_multi_caps(&caps);
|
||||
if (wt == BURN_WRITE_NONE && !(flag & 3)) {
|
||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||
0x0002012b,
|
||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Drive offers no suitable write mode with this job",
|
||||
0, 0);
|
||||
}
|
||||
return wt;
|
||||
}
|
||||
|
||||
|
||||
/* ts A70213 : new API function */
|
||||
void burn_write_opts_set_fillup(struct burn_write_opts *opts,int fill_up_media)
|
||||
{
|
||||
opts->fill_up_media = !!fill_up_media;
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/* ts A70303: API */
|
||||
void burn_write_opts_set_force(struct burn_write_opts *opts, int use_force)
|
||||
{
|
||||
opts->force_is_set = !!use_force;
|
||||
}
|
||||
|
||||
|
||||
/* ts A80412: API */
|
||||
void burn_write_opts_set_stream_recording(struct burn_write_opts *opts,
|
||||
int value)
|
||||
{
|
||||
opts->do_stream_recording = value;
|
||||
}
|
||||
|
||||
|
||||
/* ts A91115: API */
|
||||
void burn_write_opts_set_dvd_obs(struct burn_write_opts *opts, int obs)
|
||||
{
|
||||
if (obs != 0 && obs != 32 * 1024 && obs != 64 * 1024)
|
||||
return;
|
||||
opts->dvd_obs_override = obs;
|
||||
}
|
||||
|
||||
|
||||
/* ts A91115: API */
|
||||
void burn_write_opts_set_stdio_fsync(struct burn_write_opts *opts, int rythm)
|
||||
{
|
||||
if (rythm == -1)
|
||||
opts->stdio_fsync_size = 0;
|
||||
else if (rythm == 0)
|
||||
opts->stdio_fsync_size = Libburn_stdio_fsync_limiT;
|
||||
else if (rythm >= 32)
|
||||
opts->stdio_fsync_size = rythm;
|
||||
}
|
||||
|
||||
|
||||
/* ts A70901: API */
|
||||
struct burn_drive *burn_write_opts_get_drive(struct burn_write_opts *opts)
|
||||
{
|
||||
return opts->drive;
|
||||
}
|
||||
|
||||
|
||||
void burn_read_opts_set_raw(struct burn_read_opts *opts, int raw)
|
||||
{
|
||||
opts->raw = raw;
|
||||
@ -198,3 +475,4 @@ void burn_read_opts_set_hardware_error_retries(struct burn_read_opts *opts,
|
||||
{
|
||||
opts->hardware_error_retries = hardware_error_retries;
|
||||
}
|
||||
|
||||
|
@ -1,3 +1,9 @@
|
||||
|
||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
#ifndef BURN__OPTIONS_H
|
||||
#define BURN__OPTIONS_H
|
||||
|
||||
@ -32,6 +38,38 @@ struct burn_write_opts
|
||||
/** Perform calibration of the drive's laser before beginning the
|
||||
write. */
|
||||
unsigned int perform_opc:1;
|
||||
|
||||
/* ts A61219 : Output block size to trigger buffer flush if hit.
|
||||
-1 with CD, 32 kB with DVD */
|
||||
int obs;
|
||||
int obs_pad; /* 1=pad up last block to obs */
|
||||
|
||||
/* ts A61222 : Start address for media which allow a choice */
|
||||
off_t start_byte;
|
||||
|
||||
/* ts A70213 : Wether to fill up the available space on media */
|
||||
int fill_up_media;
|
||||
|
||||
/* ts A70303 : Wether to override conformance checks:
|
||||
- the check wether CD write+block type is supported by the drive
|
||||
*/
|
||||
int force_is_set;
|
||||
|
||||
/* ts A80412 : whether to use WRITE12 with Streaming bit set
|
||||
rather than WRITE10. Speeds up DVD-RAM. Might help with BD-RE.
|
||||
This gets transferred to burn_drive.do_stream_recording
|
||||
*/
|
||||
int do_stream_recording;
|
||||
|
||||
/* ts A91115 : override value for .obs on DVD media.
|
||||
Only values 0, 32K and 64K are allowed for now. */
|
||||
int dvd_obs_override;
|
||||
|
||||
/* ts A91115 : size of the fsync() interval for stdio writing.
|
||||
Values 0 or >= 32 counted in 2 KB blocks. */
|
||||
int stdio_fsync_size;
|
||||
|
||||
|
||||
/** A disc can have a media catalog number */
|
||||
int has_mediacatalog;
|
||||
unsigned char mediacatalog[13];
|
||||
@ -42,6 +80,11 @@ struct burn_write_opts
|
||||
unsigned char multi;
|
||||
};
|
||||
|
||||
/* Default value for burn_write_opts.stdio_flush_size
|
||||
*/
|
||||
#define Libburn_stdio_fsync_limiT 8192
|
||||
|
||||
|
||||
/** Options for disc reading operations. This should be created with
|
||||
burn_read_opts_new() and freed with burn_read_opts_free(). */
|
||||
struct burn_read_opts
|
||||
|
88
libburn/os-dummy.h
Normal file
88
libburn/os-dummy.h
Normal file
@ -0,0 +1,88 @@
|
||||
|
||||
/* os-dummy.h
|
||||
Operating system specific libburn definitions and declarations. Included
|
||||
by os.h in case of compilation for
|
||||
Unknown POSIX like systems
|
||||
with the dummy MMC transport adapter sg-dummy.c
|
||||
|
||||
Copyright (C) 2009 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
|
||||
*/
|
||||
|
||||
|
||||
/** List of all signals which shall be caught by signal handlers and trigger
|
||||
a graceful abort of libburn. (See man 7 signal.)
|
||||
*/
|
||||
/* Once as system defined macros */
|
||||
#define BURN_OS_SIGNAL_MACRO_LIST \
|
||||
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, \
|
||||
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, \
|
||||
SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN, \
|
||||
SIGTTOU
|
||||
|
||||
/* Once as text 1:1 list of strings for messages and interpreters */
|
||||
#define BURN_OS_SIGNAL_NAME_LIST \
|
||||
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT", \
|
||||
"SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM", \
|
||||
"SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN", \
|
||||
"SIGTTOU"
|
||||
|
||||
/* The number of above list items */
|
||||
#define BURN_OS_SIGNAL_COUNT 16
|
||||
|
||||
/** The list of all signals which shall surely not be caught.
|
||||
It depends on the particular signal whether it can be ignored or whether
|
||||
it will lead to sudden death of the process.
|
||||
Some signals are not POSIX,
|
||||
but nevertheless ought to be ignored if they are defined.
|
||||
*/
|
||||
|
||||
#ifdef SIGWINCH
|
||||
#define BURN_OS_SIG_WINCH ,SIGWINCH
|
||||
#define BURN_OS_SIG_WINCH_CNT 1
|
||||
#else
|
||||
#define BURN_OS_SIG_WINCH
|
||||
#define BURN_OS_SIG_WINCH_CNT 0
|
||||
#endif
|
||||
|
||||
#ifdef SIGURG
|
||||
#define BURN_OS_SIG_URG ,SIGURG
|
||||
#define BURN_OS_SIG_URG_CNT 1
|
||||
#else
|
||||
#define BURN_OS_SIG_URG
|
||||
#define BURN_OS_SIG_URG_CNT 0
|
||||
#endif
|
||||
|
||||
/** The combined list of all signals which shall not be caught.
|
||||
*/
|
||||
#define BURN_OS_NON_SIGNAL_MACRO_LIST \
|
||||
SIGKILL, SIGCHLD, SIGSTOP BURN_OS_SIG_WINCH BURN_OS_SIG_URG
|
||||
|
||||
/* The number of above list items */
|
||||
#define BURN_OS_NON_SIGNAL_COUNT \
|
||||
( 3 + BURN_OS_SIG_WINCH_CNT + BURN_OS_SIG_URG_CNT )
|
||||
|
||||
|
||||
/* The maximum size for a (SCSI) i/o transaction */
|
||||
/* Important : MUST be at least 32768 ! */
|
||||
#define BURN_OS_TRANSPORT_BUFFER_SIZE 65536
|
||||
|
||||
|
||||
/* To hold the position of the most recently delivered address from
|
||||
device enumeration.
|
||||
*/
|
||||
struct burn_drive_enumerator_struct {
|
||||
int pos;
|
||||
int info_count;
|
||||
char **info_list;
|
||||
};
|
||||
|
||||
#define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \
|
||||
typedef struct burn_drive_enumerator_struct burn_drive_enumerator_t;
|
||||
|
||||
|
||||
/* The list of operating system dependent elements in struct burn_drive.
|
||||
Usually they are initialized in sg-*.c:enumerate_common().
|
||||
*/
|
||||
#define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \
|
||||
int just_a_dummy;
|
||||
|
69
libburn/os-freebsd.h
Normal file
69
libburn/os-freebsd.h
Normal file
@ -0,0 +1,69 @@
|
||||
|
||||
/* os-freebsd.h
|
||||
Operating system specific libburn definitions and declarations. Included
|
||||
by os.h in case of compilation for
|
||||
FreeBSD with CAM
|
||||
|
||||
Copyright (C) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>,
|
||||
provided under GPLv2+
|
||||
*/
|
||||
|
||||
/** List of all signals which shall be caught by signal handlers and trigger
|
||||
a graceful abort of libburn. (See man 7 signal.)
|
||||
*/
|
||||
/* Once as system defined macros */
|
||||
#define BURN_OS_SIGNAL_MACRO_LIST \
|
||||
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, \
|
||||
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, \
|
||||
SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN, \
|
||||
SIGTTOU, \
|
||||
SIGBUS, SIGPROF, SIGSYS, SIGTRAP, \
|
||||
SIGVTALRM, SIGXCPU, SIGXFSZ
|
||||
|
||||
/* Once as text 1:1 list of strings for messages and interpreters */
|
||||
#define BURN_OS_SIGNAL_NAME_LIST \
|
||||
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT", \
|
||||
"SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM", \
|
||||
"SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN", \
|
||||
"SIGTTOU", \
|
||||
"SIGBUS", "SIGPROF", "SIGSYS", "SIGTRAP", \
|
||||
"SIGVTALRM", "SIGXCPU", "SIGXFSZ"
|
||||
|
||||
/* The number of above list items */
|
||||
#define BURN_OS_SIGNAL_COUNT 23
|
||||
|
||||
/** To list all signals which shall surely not be caught */
|
||||
#define BURN_OS_NON_SIGNAL_MACRO_LIST \
|
||||
SIGKILL, SIGCHLD, SIGSTOP, SIGURG, SIGWINCH
|
||||
|
||||
/* The number of above list items */
|
||||
#define BURN_OS_NON_SIGNAL_COUNT 5
|
||||
|
||||
|
||||
/* The maximum size for a (SCSI) i/o transaction */
|
||||
/* Important : MUST be at least 32768 ! */
|
||||
/* Older BSD info says that 32 kB is maximum. But 64 kB seems to work well
|
||||
on 8-STABLE. It is by default only used with BD in streaming mode.
|
||||
So older systems should still be quite safe with this buffer max size.
|
||||
*/
|
||||
#define BURN_OS_TRANSPORT_BUFFER_SIZE 65536
|
||||
|
||||
|
||||
/** To hold all state information of BSD device enumeration
|
||||
which are now local in sg_enumerate() . So that sg_give_next_adr()
|
||||
can work in BSD and sg_enumerate() can use it.
|
||||
*/
|
||||
#define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \
|
||||
struct burn_drive_enumeration_state; \
|
||||
typedef struct burn_drive_enumeration_state *burn_drive_enumerator_t;
|
||||
|
||||
|
||||
/* The list of operating system dependent elements in struct burn_drive.
|
||||
To be initialized and used within sg-*.c .
|
||||
*/
|
||||
#define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \
|
||||
struct cam_device* cam; \
|
||||
int lock_fd; \
|
||||
int is_ahci; \
|
||||
|
||||
|
95
libburn/os-libcdio.h
Normal file
95
libburn/os-libcdio.h
Normal file
@ -0,0 +1,95 @@
|
||||
|
||||
/* os-libcdio.h
|
||||
Operating system specific libburn definitions and declarations. Included
|
||||
by os.h in case of compilation for
|
||||
Unknown X/Open-like systems
|
||||
with GNU libcdio MMC transport adapter sg-libcdio.c
|
||||
|
||||
Copyright (C) 2009 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
|
||||
*/
|
||||
|
||||
|
||||
/** List of all signals which shall be caught by signal handlers and trigger
|
||||
a graceful abort of libburn. (See man 7 signal.)
|
||||
*/
|
||||
/* Once as system defined macros */
|
||||
#define BURN_OS_SIGNAL_MACRO_LIST \
|
||||
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, \
|
||||
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, \
|
||||
SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN, \
|
||||
SIGTTOU
|
||||
|
||||
/* Once as text 1:1 list of strings for messages and interpreters */
|
||||
#define BURN_OS_SIGNAL_NAME_LIST \
|
||||
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT", \
|
||||
"SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM", \
|
||||
"SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN", \
|
||||
"SIGTTOU"
|
||||
|
||||
/* The number of above list items */
|
||||
#define BURN_OS_SIGNAL_COUNT 16
|
||||
|
||||
|
||||
/** The list of all signals which shall surely not be caught.
|
||||
It depends on the particular signal whether it can be ignored or whether
|
||||
it will lead to sudden death of the process.
|
||||
Some signals are not POSIX,
|
||||
but nevertheless ought to be ignored if they are defined.
|
||||
*/
|
||||
|
||||
#ifdef SIGWINCH
|
||||
#define BURN_OS_SIG_WINCH ,SIGWINCH
|
||||
#define BURN_OS_SIG_WINCH_CNT 1
|
||||
#else
|
||||
#define BURN_OS_SIG_WINCH
|
||||
#define BURN_OS_SIG_WINCH_CNT 0
|
||||
#endif
|
||||
|
||||
#ifdef SIGURG
|
||||
#define BURN_OS_SIG_URG ,SIGURG
|
||||
#define BURN_OS_SIG_URG_CNT 1
|
||||
#else
|
||||
#define BURN_OS_SIG_URG
|
||||
#define BURN_OS_SIG_URG_CNT 0
|
||||
#endif
|
||||
|
||||
/** The combined list of all signals which shall not be caught.
|
||||
*/
|
||||
#define BURN_OS_NON_SIGNAL_MACRO_LIST \
|
||||
SIGKILL, SIGCHLD, SIGSTOP BURN_OS_SIG_WINCH BURN_OS_SIG_URG
|
||||
|
||||
/* The number of above list items */
|
||||
#define BURN_OS_NON_SIGNAL_COUNT \
|
||||
( 3 + BURN_OS_SIG_WINCH_CNT + BURN_OS_SIG_URG_CNT )
|
||||
|
||||
|
||||
/* The maximum size for a (SCSI) i/o transaction */
|
||||
/* My Blu-ray burner LG GGW-H20 writes junk if stream recording is combined
|
||||
with buffer size 32 kB. So stream recording is allowed only with size 64k.
|
||||
Older BSD info says that 32 kB is maximum. But 64 kB seems to work well
|
||||
on 8-STABLE. It is by default only used with BD in streaming mode.
|
||||
So older systems should still be quite safe with this buffer max size.
|
||||
*/
|
||||
/* Important : MUST be at least 32768 ! */
|
||||
#define BURN_OS_TRANSPORT_BUFFER_SIZE 65536
|
||||
|
||||
|
||||
/* To hold the position of the most recently delivered address from
|
||||
device enumeration.
|
||||
*/
|
||||
struct burn_drive_enumerator_struct {
|
||||
char **ppsz_cd_drives;
|
||||
char **pos;
|
||||
};
|
||||
|
||||
#define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \
|
||||
typedef struct burn_drive_enumerator_struct burn_drive_enumerator_t;
|
||||
|
||||
|
||||
/* The list of operating system dependent elements in struct burn_drive.
|
||||
Usually they are initialized in sg-*.c:enumerate_common().
|
||||
*/
|
||||
#define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \
|
||||
void *p_cdio; /* actually a pointer to CdIo_t */ \
|
||||
char libcdio_name[4096]; /* The drive path as used by libcdio */ \
|
||||
|
83
libburn/os-linux.h
Normal file
83
libburn/os-linux.h
Normal file
@ -0,0 +1,83 @@
|
||||
|
||||
/* os-linux.h
|
||||
Operating system specific libburn definitions and declarations. Included
|
||||
by os.h in case of compilation for
|
||||
Linux kernels 2.4 and 2.6, GNU/Linux SCSI Generic (sg)
|
||||
|
||||
Copyright (C) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
|
||||
/** List of all signals which shall be caught by signal handlers and trigger
|
||||
a graceful abort of libburn. (See man 7 signal.)
|
||||
*/
|
||||
/* Once as system defined macros */
|
||||
#define BURN_OS_SIGNAL_MACRO_LIST \
|
||||
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, \
|
||||
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, \
|
||||
SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN, \
|
||||
SIGTTOU, \
|
||||
SIGBUS, SIGPOLL, SIGPROF, SIGSYS, SIGTRAP, \
|
||||
SIGVTALRM, SIGXCPU, SIGXFSZ
|
||||
|
||||
/* Once as text 1:1 list of strings for messages and interpreters */
|
||||
#define BURN_OS_SIGNAL_NAME_LIST \
|
||||
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT", \
|
||||
"SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM", \
|
||||
"SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN", \
|
||||
"SIGTTOU", \
|
||||
"SIGBUS", "SIGPOLL", "SIGPROF", "SIGSYS", "SIGTRAP", \
|
||||
"SIGVTALRM", "SIGXCPU", "SIGXFSZ"
|
||||
|
||||
/* The number of above list items */
|
||||
#define BURN_OS_SIGNAL_COUNT 24
|
||||
|
||||
/** To list all signals which shall surely not be caught */
|
||||
#define BURN_OS_NON_SIGNAL_MACRO_LIST \
|
||||
SIGKILL, SIGCHLD, SIGSTOP, SIGURG, SIGWINCH
|
||||
|
||||
/* The number of above list items */
|
||||
#define BURN_OS_NON_SIGNAL_COUNT 5
|
||||
|
||||
|
||||
/* The maximum size for a (SCSI) i/o transaction */
|
||||
/* Important : MUST be at least 32768 ! */
|
||||
/* ts A70523 : >32k seems not good with kernel 2.4 USB drivers and audio
|
||||
#define BURN_OS_TRANSPORT_BUFFER_SIZE 32768
|
||||
*/
|
||||
/* ts A80414 : curbed in write.c CD media to Libburn_cd_obS = 32 kiB
|
||||
re-enlarged transport to 64 kiB for BD-RE experiments
|
||||
*/
|
||||
#define BURN_OS_TRANSPORT_BUFFER_SIZE 65536
|
||||
|
||||
|
||||
/* To hold the position of the most recently delivered address from
|
||||
device enumeration.
|
||||
*/
|
||||
struct burn_drive_enumerator_struct {
|
||||
int pos;
|
||||
int info_count;
|
||||
char **info_list;
|
||||
};
|
||||
|
||||
#define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \
|
||||
typedef struct burn_drive_enumerator_struct burn_drive_enumerator_t;
|
||||
|
||||
|
||||
/* Parameters for sibling list. See sibling_fds, sibling_fnames */
|
||||
#define BURN_OS_SG_MAX_SIBLINGS 5
|
||||
#define BURN_OS_SG_MAX_NAMELEN 16
|
||||
|
||||
/* The list of operating system dependent elements in struct burn_drive.
|
||||
Usually they are initialized in sg-*.c:enumerate_common().
|
||||
*/
|
||||
#define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \
|
||||
int fd; \
|
||||
\
|
||||
/* ts A60926 : trying to lock against growisofs /dev/srN, /dev/scdN */ \
|
||||
int sibling_count; \
|
||||
int sibling_fds[BURN_OS_SG_MAX_SIBLINGS]; \
|
||||
/* ts A70409 : DDLP */ \
|
||||
char sibling_fnames[BURN_OS_SG_MAX_SIBLINGS][BURN_OS_SG_MAX_NAMELEN];
|
||||
|
66
libburn/os-solaris.h
Normal file
66
libburn/os-solaris.h
Normal file
@ -0,0 +1,66 @@
|
||||
|
||||
/* os-solaris.h
|
||||
Operating system specific libburn definitions and declarations. Included
|
||||
by os.h in case of compilation for
|
||||
Solaris based systems, e.g. SunOS 5.11
|
||||
with Solaris uscsi MMC transport adapter sg-solaris.c
|
||||
|
||||
Copyright (C) 2010 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
|
||||
*/
|
||||
|
||||
|
||||
/** List of all signals which shall be caught by signal handlers and trigger
|
||||
a graceful abort of libburn. (See man signal.h)
|
||||
*/
|
||||
/* Once as system defined macros */
|
||||
#define BURN_OS_SIGNAL_MACRO_LIST \
|
||||
SIGHUP, SIGINT, SIGQUIT, SIGILL, SIGABRT, \
|
||||
SIGFPE, SIGSEGV, SIGPIPE, SIGALRM, SIGTERM, \
|
||||
SIGUSR1, SIGUSR2, SIGXCPU, SIGTSTP, SIGTTIN, \
|
||||
SIGTTOU
|
||||
|
||||
/* Once as text 1:1 list of strings for messages and interpreters */
|
||||
#define BURN_OS_SIGNAL_NAME_LIST \
|
||||
"SIGHUP", "SIGINT", "SIGQUIT", "SIGILL", "SIGABRT", \
|
||||
"SIGFPE", "SIGSEGV", "SIGPIPE", "SIGALRM", "SIGTERM", \
|
||||
"SIGUSR1", "SIGUSR2", "SIGXCPU", "SIGTSTP", "SIGTTIN", \
|
||||
"SIGTTOU"
|
||||
|
||||
/* The number of above list items */
|
||||
#define BURN_OS_SIGNAL_COUNT 16
|
||||
|
||||
/** To list all signals which shall surely not be caught */
|
||||
#define BURN_OS_NON_SIGNAL_MACRO_LIST \
|
||||
SIGKILL, SIGCHLD, SIGSTOP, SIGURG, SIGWINCH
|
||||
|
||||
/* The number of above list items */
|
||||
#define BURN_OS_NON_SIGNAL_COUNT 5
|
||||
|
||||
|
||||
/* The maximum size for a (SCSI) i/o transaction */
|
||||
/* Important : MUST be at least 32768 ! */
|
||||
/* My Blu-ray burner LG GGW-H20 writes junk if stream recording is combined
|
||||
with buffer size 32 kB. So stream recording is allowed only with size 64k.
|
||||
*/
|
||||
#define BURN_OS_TRANSPORT_BUFFER_SIZE 65536
|
||||
|
||||
|
||||
/* >>> */
|
||||
|
||||
/* To hold the position of the most recently delivered address from
|
||||
device enumeration.
|
||||
*/
|
||||
struct burn_drive_enumerator_struct {
|
||||
void *dir;
|
||||
};
|
||||
|
||||
#define BURN_OS_DEFINE_DRIVE_ENUMERATOR_T \
|
||||
typedef struct burn_drive_enumerator_struct burn_drive_enumerator_t;
|
||||
|
||||
|
||||
/* The list of operating system dependent elements in struct burn_drive.
|
||||
Usually they are initialized in sg-*.c:enumerate_common().
|
||||
*/
|
||||
#define BURN_OS_TRANSPORT_DRIVE_ELEMENTS \
|
||||
int fd;
|
||||
|
80
libburn/os.h
Normal file
80
libburn/os.h
Normal file
@ -0,0 +1,80 @@
|
||||
|
||||
/* os.h
|
||||
Operating system specific libburn definitions and declarations.
|
||||
The macros defined here are used by libburn modules in order to
|
||||
avoid own system dependent case distinctions.
|
||||
Copyright (C) 2009 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
|
||||
*/
|
||||
|
||||
#ifndef BURN_OS_H_INCLUDED
|
||||
#define BURN_OS_H_INCLUDED 1
|
||||
|
||||
/*
|
||||
Operating system case distinction
|
||||
*/
|
||||
|
||||
|
||||
#ifdef Libburn_use_sg_dummY
|
||||
|
||||
|
||||
/* --------- Any other system. With dummy MMC transport sg-dummy.c --------- */
|
||||
#include "os-dummy.h"
|
||||
|
||||
|
||||
#else
|
||||
#ifdef Libburn_use_libcdiO
|
||||
|
||||
|
||||
/* -------------------------- X/Open with GNU libcdio ---------------------- */
|
||||
#include "os-libcdio.h"
|
||||
|
||||
|
||||
#else
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
|
||||
/* ----------------------------- FreeBSD with CAM -------------------------- */
|
||||
#include "os-freebsd.h"
|
||||
|
||||
|
||||
#else
|
||||
#ifdef __FreeBSD_kernel__
|
||||
|
||||
|
||||
/* ----------------------- FreeBSD with CAM under Debian ------------------- */
|
||||
#include "os-freebsd.h"
|
||||
|
||||
|
||||
#else
|
||||
#ifdef __linux
|
||||
|
||||
|
||||
/* ------- Linux kernels 2.4 and 2.6 with GNU/Linux SCSI Generic (sg) ------ */
|
||||
#include "os-linux.h"
|
||||
|
||||
|
||||
#else
|
||||
#ifdef __sun
|
||||
|
||||
|
||||
/* ------- Solaris (e.g. SunOS 5.11) with uscsi ------ */
|
||||
#include "os-solaris.h"
|
||||
|
||||
|
||||
#else
|
||||
|
||||
|
||||
/* --------- Any other system. With dummy MMC transport sg-dummy.c --------- */
|
||||
#include "os-dummy.h"
|
||||
|
||||
|
||||
#endif /* ! __sun*/
|
||||
#endif /* ! __linux */
|
||||
#endif /* ! __FreeBSD__kernel__ */
|
||||
#endif /* ! __FreeBSD__ */
|
||||
#endif /* ! Libburn_use_libcdiO */
|
||||
#endif /* ! Libburn_use_sg_dummY */
|
||||
|
||||
|
||||
#endif /* ! BURN_OS_H_INCLUDED */
|
||||
|
261
libburn/read.c
261
libburn/read.c
@ -1,6 +1,13 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
/* #include <m alloc.h> ts A61013 : not in Linux man 3 malloc */
|
||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||
Copyright (c) 2006 - 2011 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <unistd.h>
|
||||
@ -12,6 +19,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"
|
||||
@ -24,13 +34,18 @@
|
||||
#include "crc.h"
|
||||
#include "debug.h"
|
||||
#include "init.h"
|
||||
#include "lec.h"
|
||||
#include "toc.h"
|
||||
#include "util.h"
|
||||
#include "sg.h"
|
||||
#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
|
||||
@ -39,7 +54,7 @@ void burn_disc_read(struct burn_drive *d, const struct burn_read_opts *o)
|
||||
int drive_lba;
|
||||
unsigned short crc;
|
||||
unsigned char fakesub[96];
|
||||
struct buffer page;
|
||||
struct buffer page; <- needs to become dynamic memory
|
||||
int speed;
|
||||
|
||||
/* ts A61007 : if this function gets revived, then these
|
||||
@ -86,7 +101,13 @@ drive, or only store a subset of the _opts structs in drives */
|
||||
fakesub[20] = 2;
|
||||
fakesub[12] = (d->toc->toc_entry[0].control << 4) +
|
||||
d->toc->toc_entry[0].adr;
|
||||
|
||||
#ifdef Libburn_no_crc_C
|
||||
crc = 0; /* dummy */
|
||||
#else
|
||||
crc = crc_ccitt(fakesub + 12, 10);
|
||||
#endif
|
||||
|
||||
fakesub[22] = crc >> 8;
|
||||
fakesub[23] = crc & 0xFF;
|
||||
write(o->subfd, fakesub, 96);
|
||||
@ -233,6 +254,8 @@ void burn_packet_process(struct burn_drive *d, unsigned char *data,
|
||||
}
|
||||
}
|
||||
crc = (*(sub + 22) << 8) + *(sub + 23);
|
||||
|
||||
#ifndef Libburn_no_crc_C
|
||||
if (crc != crc_ccitt(sub + 12, 10)) {
|
||||
burn_print(1, "sending error on %s %s\n",
|
||||
d->idata->vendor, d->idata->product);
|
||||
@ -241,6 +264,8 @@ void burn_packet_process(struct burn_drive *d, unsigned char *data,
|
||||
*/
|
||||
burn_print(1, "crc mismatch in Q\n");
|
||||
}
|
||||
#endif
|
||||
|
||||
/* else process_q(d, sub + 12); */
|
||||
/*
|
||||
if (o->subfd != -1) write(o->subfd, sub, 96); */
|
||||
@ -261,8 +286,12 @@ void burn_packet_process(struct burn_drive *d, unsigned char *data,
|
||||
/* so yeah, when you uncomment these, make them write zeros insted of crap
|
||||
static void write_empty_sector(int fd)
|
||||
{
|
||||
char sec[2352];
|
||||
static char sec[2352], initialized = 0;
|
||||
|
||||
if (!initialized) {
|
||||
memset(sec, 0, 2352);
|
||||
initialized = 1;
|
||||
}
|
||||
burn_print(1, "writing an 'empty' sector\n");
|
||||
write(fd, sec, 2352);
|
||||
}
|
||||
@ -280,3 +309,227 @@ 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 = NULL, *buffer_mem = d->buffer;
|
||||
|
||||
/*
|
||||
#define Libburn_read_data_adr_logginG 1
|
||||
*/
|
||||
#ifdef Libburn_read_data_adr_logginG
|
||||
static FILE *log_fp= NULL;
|
||||
|
||||
if(log_fp == NULL)
|
||||
log_fp = fopen("/tmp/burn_read_data_log", "a");
|
||||
if(log_fp!=NULL)
|
||||
fprintf(log_fp, "%d\n", (int) (byte_address / 2048));
|
||||
#endif /* Libburn_read_data_logginG */
|
||||
|
||||
BURN_ALLOC_MEM(buf, struct buffer, 1);
|
||||
*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);
|
||||
{ret = 0; goto ex;}
|
||||
}
|
||||
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);
|
||||
{ret = 0; goto ex;}
|
||||
} else if (d->drive_role == 3) {
|
||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||
0x00020151,
|
||||
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Read attempt on write-only drive", 0, 0);
|
||||
{ret = 0; goto ex;}
|
||||
}
|
||||
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);
|
||||
{ret = 0; goto ex;}
|
||||
}
|
||||
if (d->media_read_capacity != 0x7fffffff && byte_address >=
|
||||
((off_t) d->media_read_capacity + (off_t) 1) * (off_t) 2048) {
|
||||
if (!(flag & 2)) {
|
||||
sprintf(msg,
|
||||
"Read start address %ds larger than number of readable blocks %d",
|
||||
(int) (byte_address / 2048 + !!(byte_address % 2048)),
|
||||
d->media_read_capacity);
|
||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||
0x00020172,
|
||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||
msg, 0, 0);
|
||||
}
|
||||
{ret = 0; goto ex;}
|
||||
}
|
||||
|
||||
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);
|
||||
{ret = 0; goto ex;}
|
||||
}
|
||||
|
||||
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 == EACCES && (flag & 2)) {
|
||||
if (!(flag & 8))
|
||||
libdax_msgs_submit(libdax_messenger,
|
||||
d->global_index, 0x00020183,
|
||||
LIBDAX_MSGS_SEV_WARNING,
|
||||
LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Failed to open device (a pseudo-drive) for reading",
|
||||
errno, 0);
|
||||
} else 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;
|
||||
if (errno == EACCES && (flag & 8))
|
||||
ret= -2;
|
||||
goto ex;
|
||||
}
|
||||
if (lseek(fd, byte_address, SEEK_SET) == -1) {
|
||||
if (!(flag & 2)) {
|
||||
sprintf(msg, "Cannot address start byte %.f",
|
||||
(double) byte_address);
|
||||
libdax_msgs_submit(libdax_messenger,
|
||||
d->global_index,
|
||||
0x00020147,
|
||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||
msg, errno, 0);
|
||||
}
|
||||
ret = 0; goto ex;
|
||||
}
|
||||
}
|
||||
|
||||
d->busy = BURN_DRIVE_READING_SYNC;
|
||||
d->buffer = buf;
|
||||
|
||||
start = byte_address / 2048;
|
||||
upto = start + data_size / 2048;
|
||||
if (data_size % 2048)
|
||||
upto++;
|
||||
wpt = data;
|
||||
for (; start < upto; start += chunksize) {
|
||||
chunksize = upto - start;
|
||||
if (chunksize > 16) {
|
||||
chunksize = 16;
|
||||
cpy_size = 16 * 2048;
|
||||
} else
|
||||
cpy_size = data_size - *data_count;
|
||||
if (flag & 2)
|
||||
d->silent_on_scsi_error = 1;
|
||||
if (d->drive_role == 1) {
|
||||
err = d->read_10(d, start, chunksize, d->buffer);
|
||||
} else {
|
||||
ret = burn_stdio_read(fd, (char *) d->buffer->data,
|
||||
cpy_size, d, !!(flag & 2));
|
||||
err = 0;
|
||||
if (ret <= 0)
|
||||
err = BE_CANCELLED;
|
||||
}
|
||||
if (flag & 2)
|
||||
d->silent_on_scsi_error = sose_mem;
|
||||
if (err == BE_CANCELLED) {
|
||||
/* Try to read a smaller part of the chunk */
|
||||
if(!(flag & 4))
|
||||
for (i = 0; i < chunksize - 1; i++) {
|
||||
if (flag & 2)
|
||||
d->silent_on_scsi_error = 1;
|
||||
if (d->drive_role == 1) {
|
||||
err = d->read_10(d, start + i, 1,
|
||||
d->buffer);
|
||||
} else {
|
||||
ret = burn_stdio_read(fd,
|
||||
(char *) d->buffer->data,
|
||||
2048, d, 1);
|
||||
if (ret <= 0)
|
||||
err = BE_CANCELLED;
|
||||
}
|
||||
if (flag & 2)
|
||||
d->silent_on_scsi_error = sose_mem;
|
||||
if (err == BE_CANCELLED)
|
||||
break;
|
||||
memcpy(wpt, d->buffer->data, 2048);
|
||||
wpt += 2048;
|
||||
*data_count += 2048;
|
||||
}
|
||||
if (!(flag & 2))
|
||||
libdax_msgs_submit(libdax_messenger,
|
||||
d->global_index,
|
||||
0x00020000,
|
||||
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"burn_read_data() returns 0",
|
||||
0, 0);
|
||||
ret = 0; goto ex;
|
||||
}
|
||||
memcpy(wpt, d->buffer->data, cpy_size);
|
||||
wpt += cpy_size;
|
||||
*data_count += cpy_size;
|
||||
}
|
||||
|
||||
ret = 1;
|
||||
ex:;
|
||||
BURN_FREE_MEM(buf);
|
||||
d->buffer = buffer_mem;
|
||||
d->busy = BURN_DRIVE_IDLE;
|
||||
return ret;
|
||||
}
|
||||
|
170
libburn/sbc.c
170
libburn/sbc.c
@ -2,47 +2,181 @@
|
||||
|
||||
/* scsi block commands */
|
||||
|
||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "transport.h"
|
||||
#include "sbc.h"
|
||||
#include "spc.h"
|
||||
#include "options.h"
|
||||
|
||||
/* spc command set */
|
||||
static char SBC_LOAD[] = { 0x1b, 0, 0, 0, 3, 0 };
|
||||
static char SBC_UNLOAD[] = { 0x1b, 0, 0, 0, 2, 0 };
|
||||
|
||||
/* 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);
|
||||
|
||||
|
||||
/* START STOP UNIT as of SBC-1 and SBC-2
|
||||
0: Opcode 0x1B
|
||||
1: bit0= Immed
|
||||
bit1-7= reserved
|
||||
2: reserved
|
||||
3: reserved
|
||||
4: bit0= Start (else Stop unit)
|
||||
bit1= Load/Eject (according to Start resp. Stop)
|
||||
bit2-3= reserved
|
||||
bit4-7= Power Condition
|
||||
0= Start Valid: process Start and Load/Eject bits
|
||||
1= assume Active state
|
||||
2= assume Idle state
|
||||
3= assume Stanby state
|
||||
(5= SBC-1 only: assume Sleep state)
|
||||
7= transfer control of power conditions to logical unit
|
||||
10= force idle condition timer to 0
|
||||
11= force standby condition timer to 0
|
||||
All others are reserved.
|
||||
5: Control (set to 0)
|
||||
*/
|
||||
static unsigned char SBC_LOAD[] = { 0x1b, 0, 0, 0, 3, 0 };
|
||||
static unsigned char SBC_UNLOAD[] = { 0x1b, 0, 0, 0, 2, 0 };
|
||||
static unsigned char SBC_START_UNIT[] = { 0x1b, 0, 0, 0, 1, 0 };
|
||||
static unsigned char SBC_STOP_UNIT[] = { 0x1b, 0, 0, 0, 0, 0 };
|
||||
|
||||
void sbc_load(struct burn_drive *d)
|
||||
{
|
||||
struct command c;
|
||||
struct command *c;
|
||||
|
||||
memcpy(c.opcode, SBC_LOAD, sizeof(SBC_LOAD));
|
||||
c.retry = 1;
|
||||
c.oplen = sizeof(SBC_LOAD);
|
||||
c.dir = NO_TRANSFER;
|
||||
c.page = NULL;
|
||||
d->issue_command(d, &c);
|
||||
c = &(d->casual_command);
|
||||
if (mmc_function_spy(d, "load") <= 0)
|
||||
return;
|
||||
|
||||
scsi_init_command(c, SBC_LOAD, sizeof(SBC_LOAD));
|
||||
c->retry = 1;
|
||||
|
||||
/* ts A70921 : Had to revoke Immed because of LG GSA-4082B */
|
||||
/* c->opcode[1] |= 1; / * ts A70918 : Immed */
|
||||
|
||||
c->dir = NO_TRANSFER;
|
||||
d->issue_command(d, c);
|
||||
if (c->error)
|
||||
return;
|
||||
/* ts A70923 : Needed regardless of Immed bit. Was once 1 minute, now
|
||||
5 minutes for loading. If this does not suffice then other commands
|
||||
shall fail righteously. */
|
||||
spc_wait_unit_attention(d, 300, "waiting after START UNIT (+ LOAD)",0);
|
||||
}
|
||||
|
||||
void sbc_eject(struct burn_drive *d)
|
||||
{
|
||||
struct command c;
|
||||
struct command *c;
|
||||
|
||||
c.page = NULL;
|
||||
memcpy(c.opcode, SBC_UNLOAD, sizeof(SBC_UNLOAD));
|
||||
c.oplen = 1;
|
||||
c.oplen = sizeof(SBC_UNLOAD);
|
||||
c.page = NULL;
|
||||
c.dir = NO_TRANSFER;
|
||||
d->issue_command(d, &c);
|
||||
c = &(d->casual_command);
|
||||
if (mmc_function_spy(d, "eject") <= 0)
|
||||
return;
|
||||
|
||||
scsi_init_command(c, SBC_UNLOAD, sizeof(SBC_UNLOAD));
|
||||
/* c->opcode[1] |= 1; / * ts A70918 : Immed , ts B00109 : revoked */
|
||||
c->page = NULL;
|
||||
c->dir = NO_TRANSFER;
|
||||
d->issue_command(d, c);
|
||||
/* ts A70918 : Wait long. A late eject could surprise or hurt user.
|
||||
ts B00109 : Asynchronous eject revoked, as one cannot reliably
|
||||
distinguish out from unready.
|
||||
if (c->error)
|
||||
return;
|
||||
spc_wait_unit_attention(d, 1800, "STOP UNIT (+ EJECT)", 0);
|
||||
*/
|
||||
}
|
||||
|
||||
|
||||
/* ts A91112 : Now with flag */
|
||||
/* @param flag bit0= asynchronous waiting
|
||||
*/
|
||||
int sbc_start_unit_flag(struct burn_drive *d, int flag)
|
||||
{
|
||||
struct command *c;
|
||||
int ret;
|
||||
|
||||
c = &(d->casual_command);
|
||||
if (mmc_function_spy(d, "start_unit") <= 0)
|
||||
return 0;
|
||||
|
||||
scsi_init_command(c, SBC_START_UNIT, sizeof(SBC_START_UNIT));
|
||||
c->retry = 1;
|
||||
c->opcode[1] |= (flag & 1); /* ts A70918 : Immed */
|
||||
c->dir = NO_TRANSFER;
|
||||
d->issue_command(d, c);
|
||||
if (c->error)
|
||||
return 0;
|
||||
if (!(flag & 1))
|
||||
return 1;
|
||||
/* ts A70918 : asynchronous */
|
||||
ret = spc_wait_unit_attention(d, 1800, "START UNIT", 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
int sbc_start_unit(struct burn_drive *d)
|
||||
{
|
||||
int ret;
|
||||
|
||||
d->is_stopped = 0; /* no endless starting attempts */
|
||||
|
||||
/* Asynchronous, not to block controller by waiting */
|
||||
ret = sbc_start_unit_flag(d, 1);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
/* Synchronous to catch Pioneer DVR-216D which is ready too early.
|
||||
A pending START UNIT can prevent ejecting of the tray.
|
||||
*/
|
||||
ret = sbc_start_unit_flag(d, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* ts A90824 : Trying to reduce drive noise */
|
||||
int sbc_stop_unit(struct burn_drive *d)
|
||||
{
|
||||
struct command *c;
|
||||
int ret;
|
||||
|
||||
c = &(d->casual_command);
|
||||
if (mmc_function_spy(d, "stop_unit") <= 0)
|
||||
return 0;
|
||||
|
||||
scsi_init_command(c, SBC_STOP_UNIT, sizeof(SBC_STOP_UNIT));
|
||||
c->retry = 0;
|
||||
c->opcode[1] |= 1; /* Immed */
|
||||
c->dir = NO_TRANSFER;
|
||||
d->issue_command(d, c);
|
||||
if (c->error)
|
||||
return 0;
|
||||
ret = spc_wait_unit_attention(d, 1800, "STOP UNIT", 0);
|
||||
d->is_stopped = 1;
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/* ts A61021 : the sbc specific part of sg.c:enumerate_common()
|
||||
*/
|
||||
int sbc_setup_drive(struct burn_drive *d)
|
||||
{
|
||||
d->eject = sbc_eject;
|
||||
d->load = sbc_load;
|
||||
d->start_unit = sbc_start_unit;
|
||||
d->stop_unit = sbc_stop_unit;
|
||||
d->is_stopped = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -1,5 +1,11 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __SBC
|
||||
#define __SBC
|
||||
|
||||
@ -8,6 +14,9 @@ struct burn_drive;
|
||||
void sbc_load(struct burn_drive *);
|
||||
void sbc_eject(struct burn_drive *);
|
||||
|
||||
/* ts A61118 */
|
||||
int sbc_start_unit(struct burn_drive *);
|
||||
|
||||
/* ts A61021 : the sbc specific part of sg.c:enumerate_common()
|
||||
*/
|
||||
int sbc_setup_drive(struct burn_drive *d);
|
||||
|
277
libburn/sector.c
277
libburn/sector.c
@ -1,5 +1,14 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||
Copyright (c) 2006 - 2011 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
/* ts A61010 */
|
||||
@ -15,10 +24,23 @@
|
||||
#include "sector.h"
|
||||
#include "crc.h"
|
||||
#include "debug.h"
|
||||
#include "lec.h"
|
||||
#include "toc.h"
|
||||
#include "write.h"
|
||||
|
||||
#include "libdax_msgs.h"
|
||||
extern struct libdax_msgs *libdax_messenger;
|
||||
|
||||
#include "ecma130ab.h"
|
||||
|
||||
|
||||
#ifdef Libburn_log_in_and_out_streaM
|
||||
/* ts A61031 */
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#endif /* Libburn_log_in_and_out_streaM */
|
||||
|
||||
|
||||
/*static unsigned char isrc[] = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";*/
|
||||
|
||||
#define sector_common(X) d->alba++; d->rlba X;
|
||||
@ -44,7 +66,8 @@ static void uncook_subs(unsigned char *dest, unsigned char *source)
|
||||
int sector_get_outmode(enum burn_write_types write_type,
|
||||
enum burn_block_types block_type)
|
||||
{
|
||||
if (write_type == BURN_WRITE_SAO)
|
||||
/* ts A61103 : extended SAO condition to TAO */
|
||||
if (write_type == BURN_WRITE_SAO || write_type == BURN_WRITE_TAO)
|
||||
return 0;
|
||||
else
|
||||
switch (block_type) {
|
||||
@ -81,6 +104,15 @@ static void get_bytes(struct burn_track *track, int count, unsigned char *data)
|
||||
{
|
||||
int valid, shortage, curr, i, tr;
|
||||
|
||||
#ifdef Libburn_log_in_and_out_streaM
|
||||
/* ts A61031 */
|
||||
static int tee_fd= -1;
|
||||
if(tee_fd==-1)
|
||||
tee_fd= open("/tmp/libburn_sg_readin",
|
||||
O_WRONLY|O_CREAT|O_TRUNC,S_IRUSR|S_IWUSR);
|
||||
#endif /* Libburn_log_in_and_out_streaM */
|
||||
|
||||
|
||||
/* no track pointer means we're just generating 0s */
|
||||
if (!track) {
|
||||
memset(data, 0, count);
|
||||
@ -104,13 +136,26 @@ static void get_bytes(struct burn_track *track, int count, unsigned char *data)
|
||||
/* Next we use source data */
|
||||
curr = valid;
|
||||
if (!track->eos) {
|
||||
valid = track->source->read(track->source, data + curr, count - curr);
|
||||
if (track->source->read != NULL)
|
||||
valid = track->source->read(track->source,
|
||||
data + curr, count - curr);
|
||||
else
|
||||
valid = track->source->read_xt(track->source,
|
||||
data + curr, count - curr);
|
||||
} else valid = 0;
|
||||
|
||||
if (valid == -1) {
|
||||
if (valid <= 0) { /* ts A61031 : extended from (valid == -1) */
|
||||
track->eos = 1;
|
||||
valid = 0;
|
||||
}
|
||||
track->sourcecount += valid;
|
||||
|
||||
#ifdef Libburn_log_in_and_out_streaM
|
||||
/* ts A61031 */
|
||||
if(tee_fd!=-1 && valid>0) {
|
||||
write(tee_fd, data + curr, valid);
|
||||
}
|
||||
#endif /* Libburn_log_in_and_out_streaM */
|
||||
|
||||
curr += valid;
|
||||
shortage = count - curr;
|
||||
@ -134,6 +179,24 @@ static void get_bytes(struct burn_track *track, int count, unsigned char *data)
|
||||
if (!shortage)
|
||||
goto ex;
|
||||
|
||||
/* ts A61031 - B10103 */
|
||||
if (shortage >= count)
|
||||
track->track_data_done = 1;
|
||||
if (track->end_on_premature_eoi && shortage >= count &&
|
||||
!track->open_ended) {
|
||||
char msg[80];
|
||||
/* Memorize that premature end of input happened */
|
||||
sprintf(msg,
|
||||
"Premature end of input encountered. Missing: %d bytes",
|
||||
shortage);
|
||||
libdax_msgs_submit(libdax_messenger, -1, 0x00020180,
|
||||
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||
msg, 0,0);
|
||||
track->end_on_premature_eoi = 2;
|
||||
}
|
||||
if (track->open_ended || track->end_on_premature_eoi)
|
||||
goto ex;
|
||||
|
||||
/* If we're still short, and there's a "next" pointer, we pull from that.
|
||||
if that depletes, we'll just fill with 0s.
|
||||
*/
|
||||
@ -152,15 +215,6 @@ ex:;
|
||||
if(shortage)
|
||||
memset(data + curr, 0, shortage); /* this is old icculus.org */
|
||||
if (track->swap_source_bytes == 1) {
|
||||
|
||||
/*
|
||||
{ static int swapping_count= 0;
|
||||
fprintf(stderr,"\rlibburn_debug: swapping #%d \r",
|
||||
swapping_count);
|
||||
swapping_count++;
|
||||
}
|
||||
*/
|
||||
|
||||
for (i = 1; i < count; i += 2) {
|
||||
tr = data[i];
|
||||
data[i] = data[i-1];
|
||||
@ -171,12 +225,13 @@ ex:;
|
||||
|
||||
/* ts A61009 : seems to hand out sector start pointer in opts->drive->buffer
|
||||
and to count hand outs as well as reserved bytes */
|
||||
static unsigned char *get_sector(struct burn_write_opts *opts, int inmode)
|
||||
/* ts A61101 : added parameter track for counting written bytes */
|
||||
static unsigned char *get_sector(struct burn_write_opts *opts,
|
||||
struct burn_track *track, int inmode)
|
||||
{
|
||||
struct burn_drive *d = opts->drive;
|
||||
struct buffer *out = d->buffer;
|
||||
int outmode;
|
||||
int seclen;
|
||||
int outmode, seclen;
|
||||
unsigned char *ret;
|
||||
|
||||
outmode = get_outmode(opts);
|
||||
@ -191,16 +246,27 @@ static unsigned char *get_sector(struct burn_write_opts *opts, int inmode)
|
||||
return NULL;
|
||||
seclen += burn_subcode_length(outmode);
|
||||
|
||||
if (out->bytes + (seclen) >= BUFFER_SIZE) {
|
||||
/* ts A61219 : opts->obs is eventually a 32k trigger for DVD */
|
||||
/* (there is enough buffer size reserve for track->cdxa_conversion) */
|
||||
if (out->bytes + seclen > BUFFER_SIZE ||
|
||||
(opts->obs > 0 && out->bytes + seclen > opts->obs)) {
|
||||
int err;
|
||||
err = d->write(d, d->nwa, out);
|
||||
if (err == BE_CANCELLED)
|
||||
return NULL;
|
||||
|
||||
/* ts A61101 */
|
||||
if(track != NULL) {
|
||||
track->writecount += out->bytes;
|
||||
track->written_sectors += out->sectors;
|
||||
}
|
||||
/* ts A61119 */
|
||||
d->progress.buffered_bytes += out->bytes;
|
||||
|
||||
d->nwa += out->sectors;
|
||||
out->bytes = 0;
|
||||
out->sectors = 0;
|
||||
}
|
||||
|
||||
ret = out->data + out->bytes;
|
||||
out->bytes += seclen;
|
||||
out->sectors++;
|
||||
@ -208,6 +274,32 @@ static unsigned char *get_sector(struct burn_write_opts *opts, int inmode)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* ts A61031 */
|
||||
/* Revoke the counting of the most recent sector handed out by get_sector() */
|
||||
static void unget_sector(struct burn_write_opts *opts, int inmode)
|
||||
{
|
||||
struct burn_drive *d = opts->drive;
|
||||
struct buffer *out = d->buffer;
|
||||
int outmode;
|
||||
int seclen;
|
||||
|
||||
outmode = get_outmode(opts);
|
||||
if (outmode == 0)
|
||||
outmode = inmode;
|
||||
|
||||
/* ts A61009 : react on eventual failure of burn_sector_length()
|
||||
(should not happen if API tested properly).
|
||||
Ensures out->bytes >= out->sectors */
|
||||
seclen = burn_sector_length(outmode);
|
||||
if (seclen <= 0)
|
||||
return;
|
||||
seclen += burn_subcode_length(outmode);
|
||||
|
||||
out->bytes -= seclen;
|
||||
out->sectors--;
|
||||
}
|
||||
|
||||
|
||||
/* either inmode == outmode, or outmode == raw. anything else is bad news */
|
||||
/* ts A61010 : changed type to int in order to propagate said bad news */
|
||||
/** @return 1 is ok, <= 0 is failure */
|
||||
@ -231,7 +323,17 @@ static int convert_data(struct burn_write_opts *o, struct burn_track *track,
|
||||
return 0;
|
||||
|
||||
if ((outmode & BURN_MODE_BITS) == (inmode & BURN_MODE_BITS)) {
|
||||
/* see MMC-5 4.2.3.8.5.3 Block Format for Mode 2 form 1 Data
|
||||
Table 24 Mode 2 Formed Sector Sub-header Format */
|
||||
if (track != NULL)
|
||||
if (track->cdxa_conversion == 1)
|
||||
inlen += 8;
|
||||
|
||||
get_bytes(track, inlen, data);
|
||||
|
||||
if (track != NULL)
|
||||
if (track->cdxa_conversion == 1)
|
||||
memmove(data, data + 8, inlen - 8);
|
||||
return 1;
|
||||
}
|
||||
|
||||
@ -289,6 +391,8 @@ static void convert_subs(struct burn_write_opts *o, int inmode,
|
||||
out[0] = ~out[0];
|
||||
out[1] = ~out[1];
|
||||
break;
|
||||
/* ts A61119 : to silence compiler warnings */
|
||||
default:;
|
||||
}
|
||||
}
|
||||
|
||||
@ -322,7 +426,13 @@ a2 - lout ctrl
|
||||
q[7] = dec_to_bcd(d->toc_entry[track].pmin);
|
||||
q[8] = dec_to_bcd(d->toc_entry[track].psec);
|
||||
q[9] = dec_to_bcd(d->toc_entry[track].pframe);
|
||||
|
||||
#ifdef Libburn_no_crc_C
|
||||
crc = 0; /* dummy */
|
||||
#else
|
||||
crc = crc_ccitt(q, 10);
|
||||
#endif
|
||||
|
||||
q[10] = crc >> 8;
|
||||
q[11] = crc & 0xFF;
|
||||
d->toc_temp++;
|
||||
@ -335,7 +445,7 @@ int sector_toc(struct burn_write_opts *o, int mode)
|
||||
unsigned char *data;
|
||||
unsigned char subs[96];
|
||||
|
||||
data = get_sector(o, mode);
|
||||
data = get_sector(o, NULL, mode);
|
||||
if (data == NULL)
|
||||
return 0;
|
||||
/* ts A61010 */
|
||||
@ -343,7 +453,8 @@ int sector_toc(struct burn_write_opts *o, int mode)
|
||||
return 0;
|
||||
subcode_toc(d, mode, subs);
|
||||
convert_subs(o, mode, subs, data);
|
||||
sector_headers(o, data, mode, 1);
|
||||
if (sector_headers(o, data, mode, 1) <= 0)
|
||||
return 0;
|
||||
sector_common(++)
|
||||
return 1;
|
||||
}
|
||||
@ -355,7 +466,7 @@ int sector_pregap(struct burn_write_opts *o,
|
||||
unsigned char *data;
|
||||
unsigned char subs[96];
|
||||
|
||||
data = get_sector(o, mode);
|
||||
data = get_sector(o, NULL, mode);
|
||||
if (data == NULL)
|
||||
return 0;
|
||||
/* ts A61010 */
|
||||
@ -363,7 +474,8 @@ int sector_pregap(struct burn_write_opts *o,
|
||||
return 0;
|
||||
subcode_user(o, subs, tno, control, 0, NULL, 1);
|
||||
convert_subs(o, mode, subs, data);
|
||||
sector_headers(o, data, mode, 0);
|
||||
if (sector_headers(o, data, mode, 0) <= 0)
|
||||
return 0;
|
||||
sector_common(--)
|
||||
return 1;
|
||||
}
|
||||
@ -375,16 +487,17 @@ int sector_postgap(struct burn_write_opts *o,
|
||||
unsigned char subs[96];
|
||||
unsigned char *data;
|
||||
|
||||
data = get_sector(o, mode);
|
||||
data = get_sector(o, NULL, mode);
|
||||
if (data == NULL)
|
||||
return 0;
|
||||
/* ts A61010 */
|
||||
if (convert_data(o, NULL, mode, data) <= 0)
|
||||
return 0;;
|
||||
return 0;
|
||||
/* use last index in track */
|
||||
subcode_user(o, subs, tno, control, 1, NULL, 1);
|
||||
convert_subs(o, mode, subs, data);
|
||||
sector_headers(o, data, mode, 0);
|
||||
if (sector_headers(o, data, mode, 0) <= 0)
|
||||
return 0;
|
||||
sector_common(++)
|
||||
return 1;
|
||||
}
|
||||
@ -416,7 +529,13 @@ static void subcode_lout(struct burn_write_opts *o, unsigned char control,
|
||||
q[7] = dec_to_bcd(min);
|
||||
q[8] = dec_to_bcd(sec);
|
||||
q[9] = dec_to_bcd(frame);
|
||||
|
||||
#ifdef Libburn_no_crc_C
|
||||
crc = 0; /* dummy */
|
||||
#else
|
||||
crc = crc_ccitt(q, 10);
|
||||
#endif
|
||||
|
||||
q[10] = crc >> 8;
|
||||
q[11] = crc & 0xFF;
|
||||
}
|
||||
@ -536,7 +655,13 @@ void subcode_user(struct burn_write_opts *o, unsigned char *subcodes,
|
||||
}
|
||||
q[0] = (control << 4) + qmode;
|
||||
|
||||
|
||||
#ifdef Libburn_no_crc_C
|
||||
crc = 0; /* dummy */
|
||||
#else
|
||||
crc = crc_ccitt(q, 10);
|
||||
#endif
|
||||
|
||||
q[10] = crc >> 8;
|
||||
q[11] = crc & 0xff;
|
||||
}
|
||||
@ -547,7 +672,7 @@ int sector_lout(struct burn_write_opts *o, unsigned char control, int mode)
|
||||
unsigned char subs[96];
|
||||
unsigned char *data;
|
||||
|
||||
data = get_sector(o, mode);
|
||||
data = get_sector(o, NULL, mode);
|
||||
if (!data)
|
||||
return 0;
|
||||
/* ts A61010 */
|
||||
@ -555,7 +680,8 @@ int sector_lout(struct burn_write_opts *o, unsigned char control, int mode)
|
||||
return 0;
|
||||
subcode_lout(o, control, subs);
|
||||
convert_subs(o, mode, subs, data);
|
||||
sector_headers(o, data, mode, 0);
|
||||
if (sector_headers(o, data, mode, 0) <= 0)
|
||||
return 0;
|
||||
sector_common(++)
|
||||
return 1;
|
||||
}
|
||||
@ -566,14 +692,23 @@ int sector_data(struct burn_write_opts *o, struct burn_track *t, int psub)
|
||||
unsigned char subs[96];
|
||||
unsigned char *data;
|
||||
|
||||
data = get_sector(o, t->mode);
|
||||
if (!data)
|
||||
data = get_sector(o, t, t->mode);
|
||||
if (data == NULL)
|
||||
return 0;
|
||||
/* ts A61010 */
|
||||
if (convert_data(o, t, t->mode, data) <= 0)
|
||||
return 0;
|
||||
|
||||
if (!t->source->read_sub)
|
||||
/* ts A61031 */
|
||||
if ((t->open_ended || t->end_on_premature_eoi) && t->track_data_done) {
|
||||
unget_sector(o, t->mode);
|
||||
return 2;
|
||||
}
|
||||
|
||||
/* ts A61219 : allow track without .entry */
|
||||
if (t->entry == NULL)
|
||||
;
|
||||
else if (!t->source->read_sub)
|
||||
subcode_user(o, subs, t->entry->point,
|
||||
t->entry->control, 1, &t->isrc, psub);
|
||||
else if (!t->source->read_sub(t->source, subs, 96))
|
||||
@ -581,7 +716,8 @@ int sector_data(struct burn_write_opts *o, struct burn_track *t, int psub)
|
||||
t->entry->control, 1, &t->isrc, psub);
|
||||
convert_subs(o, t->mode, subs, data);
|
||||
|
||||
sector_headers(o, data, t->mode, 0);
|
||||
if (sector_headers(o, data, t->mode, 0) <= 0)
|
||||
return 0;
|
||||
sector_common(++)
|
||||
return 1;
|
||||
}
|
||||
@ -622,42 +758,37 @@ int sector_headers_is_ok(struct burn_write_opts *o, int mode)
|
||||
return 1;
|
||||
if (o->write_type == BURN_WRITE_SAO)
|
||||
return 1;
|
||||
|
||||
/* ts A61031 */
|
||||
if (o->write_type == BURN_WRITE_TAO)
|
||||
return 1;
|
||||
|
||||
if (mode & BURN_MODE1)
|
||||
return 2;
|
||||
return 0;
|
||||
}
|
||||
|
||||
void sector_headers(struct burn_write_opts *o, unsigned char *out,
|
||||
/* ts A90830 : changed return type to int
|
||||
@return 0= failure
|
||||
1= success
|
||||
*/
|
||||
int sector_headers(struct burn_write_opts *o, unsigned char *out,
|
||||
int mode, int leadin)
|
||||
{
|
||||
|
||||
#ifdef Libburn_ecma130ab_includeD
|
||||
|
||||
struct burn_drive *d = o->drive;
|
||||
unsigned int crc;
|
||||
int min, sec, frame;
|
||||
int modebyte = -1;
|
||||
|
||||
/* ts A61009 */
|
||||
#if 1
|
||||
int ret;
|
||||
|
||||
ret = sector_headers_is_ok(o, mode);
|
||||
if (ret != 2)
|
||||
return;
|
||||
return !!ret;
|
||||
modebyte = 1;
|
||||
|
||||
#else
|
||||
|
||||
if (mode & BURN_AUDIO) /* no headers for "audio" */
|
||||
return;
|
||||
if (o->write_type == BURN_WRITE_SAO)
|
||||
return;
|
||||
if (mode & BURN_MODE1)
|
||||
modebyte = 1;
|
||||
|
||||
#endif
|
||||
|
||||
/* ts A61009 : now ensured by burn_disc_write_is_ok() */
|
||||
/* a ssert(modebyte == 1); */
|
||||
|
||||
out[0] = 0;
|
||||
memset(out + 1, 0xFF, 10); /* sync */
|
||||
out[11] = 0;
|
||||
@ -676,7 +807,13 @@ void sector_headers(struct burn_write_opts *o, unsigned char *out,
|
||||
out[15] = modebyte;
|
||||
}
|
||||
if (mode & BURN_MODE1) {
|
||||
|
||||
#ifdef Libburn_no_crc_C
|
||||
crc = 0; /* dummy */
|
||||
#else
|
||||
crc = crc_32(out, 2064);
|
||||
#endif
|
||||
|
||||
out[2064] = crc & 0xFF;
|
||||
crc >>= 8;
|
||||
out[2065] = crc & 0xFF;
|
||||
@ -687,10 +824,33 @@ void sector_headers(struct burn_write_opts *o, unsigned char *out,
|
||||
}
|
||||
if (mode & BURN_MODE1) {
|
||||
memset(out + 2068, 0, 8);
|
||||
parity_p(out);
|
||||
parity_q(out);
|
||||
burn_rspc_parity_p(out);
|
||||
burn_rspc_parity_q(out);
|
||||
}
|
||||
scramble(out);
|
||||
burn_ecma130_scramble(out);
|
||||
return 1;
|
||||
|
||||
#else /* Libburn_ecma130ab_includeD */
|
||||
|
||||
int ret;
|
||||
|
||||
ret = sector_headers_is_ok(o, mode);
|
||||
if (ret != 2)
|
||||
return (!! ret);
|
||||
|
||||
/* ts A90830 : lec.c is copied from cdrdao.
|
||||
I have no idea yet how lec.c implements the Reed-Solomon encoding
|
||||
which is described in ECMA-130 for CD-ROM.
|
||||
So this got removed for now.
|
||||
*/
|
||||
libdax_msgs_submit(libdax_messenger, o->drive->global_index,
|
||||
0x0002010a,
|
||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Raw CD write modes are not supported", 0, 0);
|
||||
return 0;
|
||||
|
||||
#endif /* ! Libburn_ecma130ab_includeD */
|
||||
|
||||
}
|
||||
|
||||
#if 0
|
||||
@ -736,15 +896,24 @@ void process_q(struct burn_drive *d, unsigned char *q)
|
||||
#endif
|
||||
|
||||
/* this needs more info. subs in the data? control/adr? */
|
||||
|
||||
/* ts A61119 : One should not use inofficial compiler extensions.
|
||||
>>> Some day this function needs to be implemented. At least for now
|
||||
the result does not match the "mode" of cdrecord -toc.
|
||||
*/
|
||||
/*
|
||||
#warning sector_identify needs to be written
|
||||
*/
|
||||
int sector_identify(unsigned char *data)
|
||||
{
|
||||
scramble(data);
|
||||
|
||||
/*
|
||||
burn_ecma130_scramble(data);
|
||||
check mode byte for 1 or 2
|
||||
test parity to see if it's a valid sector
|
||||
if invalid, return BURN_MODE_AUDIO;
|
||||
else return mode byte (what about mode 2 formless? heh)
|
||||
*/
|
||||
|
||||
return BURN_MODE1;
|
||||
}
|
||||
|
@ -1,5 +1,10 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
#ifndef __SECTOR
|
||||
#define __SECTOR
|
||||
|
||||
@ -22,7 +27,7 @@ int sector_data(struct burn_write_opts *, struct burn_track *t, int psub);
|
||||
/* ts A61009 */
|
||||
int sector_headers_is_ok(struct burn_write_opts *o, int mode);
|
||||
|
||||
void sector_headers(struct burn_write_opts *, unsigned char *,
|
||||
int sector_headers(struct burn_write_opts *, unsigned char *,
|
||||
int mode, int leadin);
|
||||
void subcode_user(struct burn_write_opts *, unsigned char *s,
|
||||
unsigned char tno, unsigned char control,
|
||||
|
353
libburn/sg-dummy.c
Normal file
353
libburn/sg-dummy.c
Normal file
@ -0,0 +1,353 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
/*
|
||||
Copyright (c) 2009 - 2010 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
|
||||
/*
|
||||
|
||||
This is the main operating system dependent SCSI part of libburn. It implements
|
||||
the transport level aspects of SCSI control and command i/o.
|
||||
|
||||
Present implementation: default dummy which enables libburn only to work
|
||||
with stdio: pseudo drive addresses.
|
||||
For real implementations see sg-linux.c, sg-freebsd.c,
|
||||
sg-libcdio.c
|
||||
*/
|
||||
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef Libburn_os_has_statvfS
|
||||
#include <sys/statvfs.h>
|
||||
#endif /* Libburn_os_has_stavtfS */
|
||||
|
||||
#include "transport.h"
|
||||
#include "drive.h"
|
||||
#include "sg.h"
|
||||
#include "spc.h"
|
||||
#include "mmc.h"
|
||||
#include "sbc.h"
|
||||
#include "debug.h"
|
||||
#include "toc.h"
|
||||
#include "util.h"
|
||||
#include "init.h"
|
||||
|
||||
#include "libdax_msgs.h"
|
||||
extern struct libdax_msgs *libdax_messenger;
|
||||
|
||||
|
||||
/** Returns the id string of the SCSI transport adapter and eventually
|
||||
needed operating system facilities.
|
||||
This call is usable even if sg_initialize() was not called yet. In that
|
||||
case a preliminary constant message might be issued if detailed info is
|
||||
not available yet.
|
||||
@param msg returns id string
|
||||
@param flag unused yet, submit 0
|
||||
@return 1 = success, <=0 = failure
|
||||
*/
|
||||
int sg_id_string(char msg[1024], int flag)
|
||||
{
|
||||
strcpy(msg, "internal X/Open adapter sg-dummy");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/** Performs global initialization of the SCSI transport adapter and eventually
|
||||
needed operating system facilities. Checks for compatibility supporting
|
||||
software components.
|
||||
@param msg returns ids and/or error messages of eventual helpers
|
||||
@param flag unused yet, submit 0
|
||||
@return 1 = success, <=0 = failure
|
||||
*/
|
||||
int sg_initialize(char msg[1024], int flag)
|
||||
{
|
||||
return sg_id_string(msg, 0);
|
||||
}
|
||||
|
||||
|
||||
/** Performs global finalization of the SCSI transport adapter and eventually
|
||||
needed operating system facilities. Releases globally aquired resources.
|
||||
@param flag unused yet, submit 0
|
||||
@return 1 = success, <=0 = failure
|
||||
*/
|
||||
int sg_shutdown(int flag)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
|
||||
struct burn_drive which are defined in os-*.h.
|
||||
This will be called when a burn_drive gets disposed.
|
||||
@param d the drive to be finalized
|
||||
@param flag unused yet, submit 0
|
||||
@return 1 = success, <=0 = failure
|
||||
*/
|
||||
int sg_dispose_drive(struct burn_drive *d, int flag)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/** Returns the next index number and the next enumerated drive address.
|
||||
The enumeration has to cover all available and accessible drives. It is
|
||||
allowed to return addresses of drives which are not available but under
|
||||
some (even exotic) circumstances could be available. It is on the other
|
||||
hand allowed, only to hand out addresses which can really be used right
|
||||
in the moment of this call. (This implementation chooses the former.)
|
||||
@param idx An opaque handle. Make no own theories about it.
|
||||
@param adr Takes the reply
|
||||
@param adr_size Gives maximum size of reply including final 0
|
||||
@param initialize 1 = start new,
|
||||
0 = continue, use no other values for now
|
||||
-1 = finish
|
||||
@return 1 = reply is a valid address , 0 = no further address available
|
||||
-1 = severe error (e.g. adr_size too small)
|
||||
*/
|
||||
int sg_give_next_adr(burn_drive_enumerator_t *idx,
|
||||
char adr[], int adr_size, int initialize)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** Brings all available, not-whitelist-banned, and accessible drives into
|
||||
libburn's list of drives.
|
||||
*/
|
||||
/* ts A61115: replacing call to sg-implementation internals from drive.c */
|
||||
int scsi_enumerate_drives(void)
|
||||
{
|
||||
libdax_msgs_submit(libdax_messenger, -1, 0x0002016b,
|
||||
LIBDAX_MSGS_SEV_WARNING, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"No MMC transport adapter is present. Running on sg-dummy.c.",
|
||||
0, 0);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/** Tells wether libburn has the given drive in use or exclusively reserved.
|
||||
If it is "open" then libburn will eventually call sg_release() on it when
|
||||
it is time to give up usage resp. reservation.
|
||||
*/
|
||||
/** Published as burn_drive.drive_is_open() */
|
||||
int sg_drive_is_open(struct burn_drive * d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** Opens the drive for SCSI commands and - if burn activities are prone
|
||||
to external interference on your system - obtains an exclusive access lock
|
||||
on the drive. (Note: this is not physical tray locking.)
|
||||
A drive that has been opened with sg_grab() will eventually be handed
|
||||
over to sg_release() for closing and unreserving.
|
||||
*/
|
||||
int sg_grab(struct burn_drive *d)
|
||||
{
|
||||
libdax_msgs_submit(libdax_messenger, d->global_index, 0x0002016a,
|
||||
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"No MMC transport adapter is present. Running on sg-dummy.c.",
|
||||
0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** Gives up the drive for SCSI commands and releases eventual access locks.
|
||||
(Note: this is not physical tray locking.)
|
||||
*/
|
||||
int sg_release(struct burn_drive *d)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** Sends a SCSI command to the drive, receives reply and evaluates wether
|
||||
the command succeeded or shall be retried or finally failed.
|
||||
Returned SCSI errors shall not lead to a return value indicating failure.
|
||||
The callers get notified by c->error. An SCSI failure which leads not to
|
||||
a retry shall be notified via scsi_notify_error().
|
||||
The Libburn_log_sg_commandS facility might be of help when problems with
|
||||
a drive have to be examined. It shall stay disabled for normal use.
|
||||
@return: 1 success , <=0 failure
|
||||
*/
|
||||
int sg_issue_command(struct burn_drive *d, struct command *c)
|
||||
{
|
||||
libdax_msgs_submit(libdax_messenger, d->global_index, 0x0002016a,
|
||||
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"No MMC transport adapter is present. Running on sg-dummy.c.",
|
||||
0, 0);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/** Tries to obtain SCSI address parameters.
|
||||
@return 1 is success , 0 is failure
|
||||
*/
|
||||
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
|
||||
int *target_no, int *lun_no)
|
||||
{
|
||||
libdax_msgs_submit(libdax_messenger, -1, 0x0002016c,
|
||||
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"No MMC transport adapter is present. Running on sg-dummy.c.",
|
||||
0, 0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** Tells wether a text is a persistent address as listed by the enumeration
|
||||
functions.
|
||||
*/
|
||||
int sg_is_enumerable_adr(char *adr)
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
/* Return 1 if the given path leads to a regular file or a device that can be
|
||||
seeked, read, and possibly written with 2 kB granularity.
|
||||
*/
|
||||
int burn_os_is_2k_seekrw(char *path, int flag)
|
||||
{
|
||||
struct stat stbuf;
|
||||
|
||||
if (stat(path, &stbuf) == -1)
|
||||
return 0;
|
||||
if (S_ISREG(stbuf.st_mode))
|
||||
return 1;
|
||||
if (S_ISBLK(stbuf.st_mode))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** Estimate the potential payload capacity of a file address.
|
||||
@param path The address of the file to be examined. If it does not
|
||||
exist yet, then the directory will be inquired.
|
||||
@param bytes The pointed value gets modified, but only if an estimation is
|
||||
possible.
|
||||
@return -2 = cannot perform necessary operations on file object
|
||||
-1 = neither path nor dirname of path exist
|
||||
0 = could not estimate size capacity of file object
|
||||
1 = estimation has been made, bytes was set
|
||||
*/
|
||||
int burn_os_stdio_capacity(char *path, off_t *bytes)
|
||||
{
|
||||
struct stat stbuf;
|
||||
|
||||
#ifdef Libburn_os_has_statvfS
|
||||
struct statvfs vfsbuf;
|
||||
#endif
|
||||
|
||||
char *testpath = NULL, *cpt;
|
||||
long blocks;
|
||||
off_t add_size = 0;
|
||||
int ret;
|
||||
|
||||
BURN_ALLOC_MEM(testpath, char, 4096);
|
||||
|
||||
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)
|
||||
{ret = -1; goto ex;}
|
||||
|
||||
#ifdef Libburn_if_this_was_linuX
|
||||
|
||||
} else if(S_ISBLK(stbuf.st_mode)) {
|
||||
fd = open(path, open_mode);
|
||||
if (fd == -1)
|
||||
{ret = -2; goto ex;}
|
||||
ret = ioctl(fd, BLKGETSIZE, &blocks);
|
||||
close(fd);
|
||||
if (ret == -1)
|
||||
{ret = -2; goto ex;}
|
||||
*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
|
||||
{ret = 0; goto ex;}
|
||||
|
||||
if (testpath[0]) {
|
||||
|
||||
#ifdef Libburn_os_has_statvfS
|
||||
|
||||
if (statvfs(testpath, &vfsbuf) == -1)
|
||||
{ret = -2; goto ex;}
|
||||
*bytes = add_size + ((off_t) vfsbuf.f_frsize) *
|
||||
(off_t) vfsbuf.f_bavail;
|
||||
|
||||
#else /* Libburn_os_has_statvfS */
|
||||
|
||||
{ret = 0; goto ex;}
|
||||
|
||||
#endif /* ! Libburn_os_has_stavtfS */
|
||||
|
||||
}
|
||||
ret = 1;
|
||||
ex:;
|
||||
BURN_FREE_MEM(testpath);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* ts A91122 : an interface to open(O_DIRECT) or similar OS tricks. */
|
||||
|
||||
#ifdef Libburn_read_o_direcT
|
||||
|
||||
/* No special O_DIRECT-like precautions are implemented here */
|
||||
|
||||
#endif /* Libburn_read_o_direcT */
|
||||
|
||||
|
||||
int burn_os_open_track_src(char *path, int open_flags, int flag)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open(path, open_flags);
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
void *burn_os_alloc_buffer(size_t amount, int flag)
|
||||
{
|
||||
void *buf = NULL;
|
||||
|
||||
buf = calloc(1, amount);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
int burn_os_free_buffer(void *buffer, size_t amount, int flag)
|
||||
{
|
||||
if (buffer == NULL)
|
||||
return 0;
|
||||
free(buffer);
|
||||
return 1;
|
||||
}
|
||||
|
824
libburn/sg-freebsd-port.c
Normal file
824
libburn/sg-freebsd-port.c
Normal file
@ -0,0 +1,824 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
/*
|
||||
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
|
||||
This is the main operating system dependent SCSI part of libburn. It implements
|
||||
the transport level aspects of SCSI control and command i/o.
|
||||
|
||||
Present implementation: FreeBSD CAM (untested)
|
||||
|
||||
|
||||
PORTING:
|
||||
|
||||
Porting libburn typically will consist of adding a new operating system case
|
||||
to the following switcher files:
|
||||
os.h Operating system specific libburn definitions and declarations.
|
||||
sg.c Operating system dependent transport level modules.
|
||||
and of deriving the following system specific files from existing examples:
|
||||
os-*.h Included by os.h. You will need some general system knowledge
|
||||
about signals and knowledge about the storage object needs of your
|
||||
transport level module sg-*.c.
|
||||
|
||||
sg-*.c This source module. You will need special system knowledge about
|
||||
how to detect all potentially available drives, how to open them,
|
||||
eventually how to exclusively reserve them, how to perform
|
||||
SCSI transactions, how to inquire the (pseudo-)SCSI driver.
|
||||
You will not need to care about CD burning, MMC or other high-level
|
||||
SCSI aspects.
|
||||
|
||||
Said sg-*.c operations are defined by a public function interface, which has
|
||||
to be implemented in a way that provides libburn with the desired services:
|
||||
|
||||
sg_id_string() returns an id string of the SCSI transport adapter.
|
||||
It may be called before initialization but then may
|
||||
return only a preliminary id.
|
||||
|
||||
sg_initialize() performs global initialization of the SCSI transport
|
||||
adapter and eventually needed operating system
|
||||
facilities. Checks for compatibility of supporting
|
||||
software components.
|
||||
|
||||
sg_shutdown() performs global finalizations and releases golbally
|
||||
aquired resources.
|
||||
|
||||
sg_give_next_adr() iterates over the set of potentially useful drive
|
||||
address strings.
|
||||
|
||||
scsi_enumerate_drives() brings all available, not-whitelist-banned, and
|
||||
accessible drives into libburn's list of drives.
|
||||
|
||||
sg_dispose_drive() finalizes adapter specifics of struct burn_drive
|
||||
on destruction. Releases resources which were aquired
|
||||
underneath scsi_enumerate_drives().
|
||||
|
||||
sg_drive_is_open() tells wether libburn has the given drive in use.
|
||||
|
||||
sg_grab() opens the drive for SCSI commands and ensures
|
||||
undisturbed access.
|
||||
|
||||
sg_release() closes a drive opened by sg_grab()
|
||||
|
||||
sg_issue_command() sends a SCSI command to the drive, receives reply,
|
||||
and evaluates wether the command succeeded or shall
|
||||
be retried or finally failed.
|
||||
|
||||
sg_obtain_scsi_adr() tries to obtain SCSI address parameters.
|
||||
|
||||
|
||||
burn_os_is_2k_seekrw() tells whether the given path leads to a file object
|
||||
that can be used in 2 kB granularity by lseek(2),
|
||||
read(2), and possibly write(2) if not read-only.
|
||||
E.g. a USB stick or a hard disk.
|
||||
|
||||
burn_os_stdio_capacity() estimates the emulated media space of stdio-drives.
|
||||
|
||||
burn_os_open_track_src() opens a disk file in a way that allows best
|
||||
throughput with file reading and/or SCSI write command
|
||||
transmission.
|
||||
|
||||
burn_os_alloc_buffer() allocates a memory area that is suitable for file
|
||||
descriptors issued by burn_os_open_track_src().
|
||||
The buffer size may be rounded up for alignment
|
||||
reasons.
|
||||
|
||||
burn_os_free_buffer() delete a buffer obtained by burn_os_alloc_buffer().
|
||||
|
||||
|
||||
Porting hints are marked by the text "PORTING:".
|
||||
Send feedback to libburn-hackers@pykix.org .
|
||||
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
|
||||
/** PORTING : ------- OS dependent headers and definitions ------ */
|
||||
|
||||
#include <errno.h>
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include <sys/poll.h>
|
||||
#include <camlib.h>
|
||||
#include <cam/scsi/scsi_message.h>
|
||||
#include <cam/scsi/scsi_pass.h>
|
||||
|
||||
#include <err.h> /* XXX */
|
||||
|
||||
|
||||
/* ts A70909 */
|
||||
#include <sys/statvfs.h>
|
||||
|
||||
|
||||
/** PORTING : ------ libburn portable headers and definitions ----- */
|
||||
|
||||
#include "transport.h"
|
||||
#include "drive.h"
|
||||
#include "sg.h"
|
||||
#include "spc.h"
|
||||
#include "mmc.h"
|
||||
#include "sbc.h"
|
||||
#include "debug.h"
|
||||
#include "toc.h"
|
||||
#include "util.h"
|
||||
|
||||
#include "libdax_msgs.h"
|
||||
extern struct libdax_msgs *libdax_messenger;
|
||||
|
||||
|
||||
/* is in portable part of libburn */
|
||||
int burn_drive_is_banned(char *device_address);
|
||||
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* ts A61115: Private functions. Port only if needed by public functions */
|
||||
/* (Public functions are listed below) */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
|
||||
/* Helper function for scsi_give_next_adr() */
|
||||
static int sg_init_enumerator(burn_drive_enumerator_t *idx)
|
||||
{
|
||||
idx->skip_device = 0;
|
||||
|
||||
if ((idx->fd = open(XPT_DEVICE, O_RDWR)) == -1) {
|
||||
warn("couldn't open %s", XPT_DEVICE);
|
||||
return -1;
|
||||
}
|
||||
|
||||
memset(&(idx->ccb), 0, sizeof(union ccb));
|
||||
|
||||
idx->ccb.ccb_h.path_id = CAM_XPT_PATH_ID;
|
||||
idx->ccb.ccb_h.target_id = CAM_TARGET_WILDCARD;
|
||||
idx->ccb.ccb_h.target_lun = CAM_LUN_WILDCARD;
|
||||
|
||||
idx->ccb.ccb_h.func_code = XPT_DEV_MATCH;
|
||||
idx->bufsize = sizeof(struct dev_match_result) * 100;
|
||||
idx->ccb.cdm.match_buf_len = idx->bufsize;
|
||||
idx->ccb.cdm.matches = (struct dev_match_result *)
|
||||
calloc(1, idx->bufsize);
|
||||
if (idx->ccb.cdm.matches == NULL) {
|
||||
warnx("cannot allocate memory for matches");
|
||||
close(idx->fd);
|
||||
return -1;
|
||||
}
|
||||
idx->ccb.cdm.num_matches = 0;
|
||||
idx->i = idx->ccb.cdm.num_matches; /* to trigger buffer load */
|
||||
|
||||
/*
|
||||
* We fetch all nodes, since we display most of them in the default
|
||||
* case, and all in the verbose case.
|
||||
*/
|
||||
idx->ccb.cdm.num_patterns = 0;
|
||||
idx->ccb.cdm.pattern_buf_len = 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Helper function for scsi_give_next_adr() */
|
||||
static int sg_next_enumeration_buffer(burn_drive_enumerator_t *idx)
|
||||
{
|
||||
/*
|
||||
* We do the ioctl multiple times if necessary, in case there are
|
||||
* more than 100 nodes in the EDT.
|
||||
*/
|
||||
if (ioctl(idx->fd, CAMIOCOMMAND, &(idx->ccb)) == -1) {
|
||||
warn("error sending CAMIOCOMMAND ioctl");
|
||||
return -1;
|
||||
}
|
||||
|
||||
if ((idx->ccb.ccb_h.status != CAM_REQ_CMP)
|
||||
|| ((idx->ccb.cdm.status != CAM_DEV_MATCH_LAST)
|
||||
&& (idx->ccb.cdm.status != CAM_DEV_MATCH_MORE))) {
|
||||
warnx("got CAM error %#x, CDM error %d\n",
|
||||
idx->ccb.ccb_h.status, idx->ccb.cdm.status);
|
||||
return -1;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int sg_close_drive(struct burn_drive * d)
|
||||
{
|
||||
if (d->cam != NULL) {
|
||||
cam_close_device(d->cam);
|
||||
d->cam = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* PORTING: Private functions which contain publicly needed functionality. */
|
||||
/* Their portable part must be performed. So it is probably best */
|
||||
/* to replace the non-portable part and to call these functions */
|
||||
/* in your port, too. */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
|
||||
/** Wraps a detected drive into libburn structures and hands it over to
|
||||
libburn drive list.
|
||||
*/
|
||||
static void enumerate_common(char *fname, int bus_no, int host_no,
|
||||
int channel_no, int target_no, int lun_no)
|
||||
{
|
||||
int ret;
|
||||
struct burn_drive out;
|
||||
|
||||
/* General libburn drive setup */
|
||||
burn_setup_drive(&out, fname);
|
||||
|
||||
/* This transport adapter uses SCSI-family commands and models
|
||||
(seems the adapter would know better than its boss, if ever) */
|
||||
ret = burn_scsi_setup_drive(&out, bus_no, host_no, channel_no,
|
||||
target_no, lun_no, 0);
|
||||
if (ret<=0)
|
||||
return;
|
||||
|
||||
/* PORTING: ------------------- non portable part --------------- */
|
||||
|
||||
/* Operating system adapter is CAM */
|
||||
/* Adapter specific handles and data */
|
||||
out.cam = NULL;
|
||||
|
||||
/* PORTING: ---------------- end of non portable part ------------ */
|
||||
|
||||
/* Adapter specific functions with standardized names */
|
||||
out.grab = sg_grab;
|
||||
out.release = sg_release;
|
||||
out.drive_is_open = sg_drive_is_open;
|
||||
out.issue_command = sg_issue_command;
|
||||
/* Finally register drive and inquire drive information */
|
||||
burn_drive_finish_enum(&out);
|
||||
}
|
||||
|
||||
|
||||
/* ts A61115 */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* PORTING: Public functions. These MUST be ported. */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
|
||||
/** Returns the id string of the SCSI transport adapter and eventually
|
||||
needed operating system facilities.
|
||||
This call is usable even if sg_initialize() was not called yet. In that
|
||||
case a preliminary constant message might be issued if detailed info is
|
||||
not available yet.
|
||||
@param msg returns id string
|
||||
@param flag unused yet, submit 0
|
||||
@return 1 = success, <=0 = failure
|
||||
*/
|
||||
int sg_id_string(char msg[1024], int flag)
|
||||
{
|
||||
strcpy(msg, "internal FreeBSD CAM adapter sg-freebsd-port");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/** Performs global initialization of the SCSI transport adapter and eventually
|
||||
needed operating system facilities. Checks for compatibility supporting
|
||||
software components.
|
||||
@param msg returns ids and/or error messages of eventual helpers
|
||||
@param flag unused yet, submit 0
|
||||
@return 1 = success, <=0 = failure
|
||||
*/
|
||||
int sg_initialize(char msg[1024], int flag)
|
||||
{
|
||||
return sg_id_string(msg, 0);
|
||||
}
|
||||
|
||||
|
||||
/** Performs global finalization of the SCSI transport adapter and eventually
|
||||
needed operating system facilities. Releases globally aquired resources.
|
||||
@param flag unused yet, submit 0
|
||||
@return 1 = success, <=0 = failure
|
||||
*/
|
||||
int sg_shutdown(int flag)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
|
||||
struct burn_drive which are defined in os-*.h.
|
||||
The eventual initialization of those components was made underneath
|
||||
scsi_enumerate_drives().
|
||||
This will be called when a burn_drive gets disposed.
|
||||
@param d the drive to be finalized
|
||||
@param flag unused yet, submit 0
|
||||
@return 1 = success, <=0 = failure
|
||||
*/
|
||||
int sg_dispose_drive(struct burn_drive *d, int flag)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/** Returns the next index number and the next enumerated drive address.
|
||||
The enumeration has to cover all available and accessible drives. It is
|
||||
allowed to return addresses of drives which are not available but under
|
||||
some (even exotic) circumstances could be available. It is on the other
|
||||
hand allowed, only to hand out addresses which can really be used right
|
||||
in the moment of this call. (This implementation chooses the latter.)
|
||||
@param idx An opaque handle. Make no own theories about it.
|
||||
@param adr Takes the reply
|
||||
@param adr_size Gives maximum size of reply including final 0
|
||||
@param initialize 1 = start new,
|
||||
0 = continue, use no other values for now
|
||||
-1 = finish
|
||||
@return 1 = reply is a valid address , 0 = no further address available
|
||||
-1 = severe error (e.g. adr_size too small)
|
||||
*/
|
||||
int sg_give_next_adr(burn_drive_enumerator_t *idx,
|
||||
char adr[], int adr_size, int initialize)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (initialize == 1) {
|
||||
ret = sg_init_enumerator(idx);
|
||||
if (ret<=0)
|
||||
return ret;
|
||||
} else if (initialize == -1) {
|
||||
if(idx->fd != -1)
|
||||
close(idx->fd);
|
||||
idx->fd = -1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
try_item:; /* This spaghetti loop keeps the number of tabs small */
|
||||
|
||||
/* Loop content from old scsi_enumerate_drives() */
|
||||
|
||||
while (idx->i >= idx->ccb.cdm.num_matches) {
|
||||
ret = sg_next_enumeration_buffer(idx);
|
||||
if (ret<=0)
|
||||
return -1;
|
||||
if (!((idx->ccb.ccb_h.status == CAM_REQ_CMP)
|
||||
&& (idx->ccb.cdm.status == CAM_DEV_MATCH_MORE)) )
|
||||
return 0;
|
||||
idx->i = 0;
|
||||
}
|
||||
|
||||
switch (idx->ccb.cdm.matches[idx->i].type) {
|
||||
case DEV_MATCH_BUS:
|
||||
break;
|
||||
case DEV_MATCH_DEVICE: {
|
||||
struct device_match_result* result;
|
||||
|
||||
result = &(idx->ccb.cdm.matches[i].result.device_result);
|
||||
if (result->flags & DEV_RESULT_UNCONFIGURED)
|
||||
idx->skip_device = 1;
|
||||
else
|
||||
idx->skip_device = 0;
|
||||
break;
|
||||
}
|
||||
case DEV_MATCH_PERIPH: {
|
||||
struct periph_match_result* result;
|
||||
char buf[64];
|
||||
|
||||
result = &(idx->ccb.cdm.matches[i].result.periph_result);
|
||||
if (idx->skip_device ||
|
||||
strcmp(result->periph_name, "pass") == 0)
|
||||
break;
|
||||
snprintf(buf, sizeof (buf), "/dev/%s%d",
|
||||
result->periph_name, result->unit_number);
|
||||
if(adr_size <= strlen(buf))
|
||||
return -1;
|
||||
strcpy(adr, buf);
|
||||
|
||||
/* Found next enumerable address */
|
||||
return 1;
|
||||
|
||||
}
|
||||
default:
|
||||
/* printf(stderr, "unknown match type\n"); */
|
||||
break;
|
||||
}
|
||||
|
||||
(idx->i)++;
|
||||
goto try_item; /* Regular function exit is return 1 above */
|
||||
}
|
||||
|
||||
|
||||
/** Brings all available, not-whitelist-banned, and accessible drives into
|
||||
libburn's list of drives.
|
||||
*/
|
||||
int scsi_enumerate_drives(void)
|
||||
{
|
||||
burn_drive_enumerator_t idx;
|
||||
int initialize = 1, ret;
|
||||
char buf[64];
|
||||
|
||||
while(1) {
|
||||
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
|
||||
initialize = 0;
|
||||
if (ret <= 0)
|
||||
break;
|
||||
if (burn_drive_is_banned(buf))
|
||||
continue;
|
||||
enumerate_common(buf, idx.result->path_id, idx.result->path_id,
|
||||
0, idx.result->target_id,
|
||||
idx.result->target_lun);
|
||||
}
|
||||
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/** Tells wether libburn has the given drive in use or exclusively reserved.
|
||||
If it is "open" then libburn will eventually call sg_release() on it when
|
||||
it is time to give up usage resp. reservation.
|
||||
*/
|
||||
/** Published as burn_drive.drive_is_open() */
|
||||
int sg_drive_is_open(struct burn_drive * d)
|
||||
{
|
||||
return (d->cam != NULL);
|
||||
}
|
||||
|
||||
|
||||
/** Opens the drive for SCSI commands and - if burn activities are prone
|
||||
to external interference on your system - obtains an exclusive access lock
|
||||
on the drive. (Note: this is not physical tray locking.)
|
||||
A drive that has been opened with sg_grab() will eventually be handed
|
||||
over to sg_release() for closing and unreserving.
|
||||
*/
|
||||
int sg_grab(struct burn_drive *d)
|
||||
{
|
||||
struct cam_device *cam;
|
||||
|
||||
if(d->cam != NULL) {
|
||||
d->released = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
cam = cam_open_device(d->devname, O_RDWR);
|
||||
if (cam == NULL) {
|
||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||
0x00020003,
|
||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Could not grab drive", 0/*os_errno*/, 0);
|
||||
return 0;
|
||||
}
|
||||
d->cam = cam;
|
||||
fcntl(cam->fd, F_SETOWN, getpid());
|
||||
d->released = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/** PORTING: Is mainly about the call to sg_close_drive() and wether it
|
||||
implements the demanded functionality.
|
||||
*/
|
||||
/** Gives up the drive for SCSI commands and releases eventual access locks.
|
||||
(Note: this is not physical tray locking.)
|
||||
*/
|
||||
int sg_release(struct burn_drive *d)
|
||||
{
|
||||
if (d->cam == NULL) {
|
||||
burn_print(1, "release an ungrabbed drive. die\n");
|
||||
return 0;
|
||||
}
|
||||
sg_close_drive(d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** Sends a SCSI command to the drive, receives reply and evaluates wether
|
||||
the command succeeded or shall be retried or finally failed.
|
||||
Returned SCSI errors shall not lead to a return value indicating failure.
|
||||
The callers get notified by c->error. An SCSI failure which leads not to
|
||||
a retry shall be notified via scsi_notify_error().
|
||||
The Libburn_log_sg_commandS facility might be of help when problems with
|
||||
a drive have to be examined. It shall stay disabled for normal use.
|
||||
@return: 1 success , <=0 failure
|
||||
*/
|
||||
int sg_issue_command(struct burn_drive *d, struct command *c)
|
||||
{
|
||||
int done = 0;
|
||||
int err;
|
||||
union ccb *ccb;
|
||||
|
||||
if (d->cam == NULL) {
|
||||
c->error = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
c->error = 0;
|
||||
|
||||
ccb = cam_getccb(d->cam);
|
||||
cam_fill_csio(&ccb->csio,
|
||||
1, /* retries */
|
||||
NULL, /* cbfncp */
|
||||
CAM_DEV_QFRZDIS, /* flags */
|
||||
MSG_SIMPLE_Q_TAG, /* tag_action */
|
||||
NULL, /* data_ptr */
|
||||
0, /* dxfer_len */
|
||||
sizeof (ccb->csio.sense_data), /* sense_len */
|
||||
0, /* cdb_len */
|
||||
30*1000); /* timeout */
|
||||
switch (c->dir) {
|
||||
case TO_DRIVE:
|
||||
ccb->csio.ccb_h.flags |= CAM_DIR_OUT;
|
||||
break;
|
||||
case FROM_DRIVE:
|
||||
ccb->csio.ccb_h.flags |= CAM_DIR_IN;
|
||||
break;
|
||||
case NO_TRANSFER:
|
||||
ccb->csio.ccb_h.flags |= CAM_DIR_NONE;
|
||||
break;
|
||||
}
|
||||
|
||||
ccb->csio.cdb_len = c->oplen;
|
||||
memcpy(&ccb->csio.cdb_io.cdb_bytes, &c->opcode, c->oplen);
|
||||
|
||||
memset(&ccb->csio.sense_data, 0, sizeof (ccb->csio.sense_data));
|
||||
|
||||
if (c->page) {
|
||||
ccb->csio.data_ptr = c->page->data;
|
||||
if (c->dir == FROM_DRIVE) {
|
||||
ccb->csio.dxfer_len = BUFFER_SIZE;
|
||||
/* touch page so we can use valgrind */
|
||||
memset(c->page->data, 0, BUFFER_SIZE);
|
||||
} else {
|
||||
|
||||
/* ts A61115: removed a ssert() */
|
||||
if(c->page->bytes <= 0)
|
||||
return 0;
|
||||
|
||||
ccb->csio.dxfer_len = c->page->bytes;
|
||||
}
|
||||
} else {
|
||||
ccb->csio.data_ptr = NULL;
|
||||
ccb->csio.dxfer_len = 0;
|
||||
}
|
||||
|
||||
do {
|
||||
err = cam_send_ccb(d->cam, ccb);
|
||||
if (err == -1) {
|
||||
libdax_msgs_submit(libdax_messenger,
|
||||
d->global_index, 0x0002010c,
|
||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Failed to transfer command to drive",
|
||||
errno, 0);
|
||||
cam_freeccb(ccb);
|
||||
sg_close_drive(d);
|
||||
d->released = 1;
|
||||
d->busy = BURN_DRIVE_IDLE;
|
||||
c->error = 1;
|
||||
return -1;
|
||||
}
|
||||
/* XXX */
|
||||
memcpy(c->sense, &ccb->csio.sense_data, ccb->csio.sense_len);
|
||||
if ((ccb->ccb_h.status & CAM_STATUS_MASK) != CAM_REQ_CMP) {
|
||||
if (!c->retry) {
|
||||
c->error = 1;
|
||||
cam_freeccb(ccb);
|
||||
return 1;
|
||||
}
|
||||
switch (scsi_error(d, c->sense, 0)) {
|
||||
case RETRY:
|
||||
done = 0;
|
||||
break;
|
||||
case FAIL:
|
||||
done = 1;
|
||||
c->error = 1;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
done = 1;
|
||||
}
|
||||
} while (!done);
|
||||
cam_freeccb(ccb);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/** Tries to obtain SCSI address parameters.
|
||||
@return 1 is success , 0 is failure
|
||||
*/
|
||||
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
|
||||
int *target_no, int *lun_no)
|
||||
{
|
||||
burn_drive_enumerator_t idx;
|
||||
int initialize = 1, ret;
|
||||
char buf[64];
|
||||
struct periph_match_result* result;
|
||||
|
||||
while(1) {
|
||||
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
|
||||
initialize = 0;
|
||||
if (ret <= 0)
|
||||
break;
|
||||
if (strcmp(path, buf) != 0)
|
||||
continue;
|
||||
result = &(idx->ccb.cdm.matches[i].result.periph_result);
|
||||
*bus_no = result->path_id;
|
||||
*host_no = result->path_id;
|
||||
*channel_no = 0;
|
||||
*target_no = result->target_id
|
||||
*lun_no = result->target_lun;
|
||||
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
|
||||
return 1;
|
||||
}
|
||||
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/** Tells wether a text is a persistent address as listed by the enumeration
|
||||
functions.
|
||||
*/
|
||||
int sg_is_enumerable_adr(char* adr)
|
||||
{
|
||||
burn_drive_enumerator_t idx;
|
||||
int initialize = 1, ret;
|
||||
char buf[64];
|
||||
|
||||
while(1) {
|
||||
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
|
||||
initialize = 0;
|
||||
if (ret <= 0)
|
||||
break;
|
||||
if (strcmp(adr, buf) == 0) {
|
||||
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/* ts B00115 */
|
||||
/* Return 1 if the given path leads to a regular file or a device that can be
|
||||
seeked, written, and read with 2 kB granularity.
|
||||
*/
|
||||
int burn_os_is_2k_seekrw(char *path, int flag)
|
||||
{
|
||||
struct stat stbuf;
|
||||
char *spt;
|
||||
int i, e;
|
||||
|
||||
if (stat(path, &stbuf) == -1)
|
||||
return 0;
|
||||
if (S_ISREG(stbuf.st_mode))
|
||||
return 1;
|
||||
if (!S_ISCHR(stbuf.st_mode))
|
||||
return 0;
|
||||
spt = strrchr(path, '/');
|
||||
if (spt == NULL)
|
||||
spt = path;
|
||||
else
|
||||
spt++;
|
||||
e = strlen(spt);
|
||||
for (i = strlen(spt) - 1; i > 0; i--)
|
||||
if (spt[i] >= '0' && spt[i] <= '9')
|
||||
e = i;
|
||||
if (strncmp(spt, "da", e) == 0) /* SCSI disk. E.g. USB stick. */
|
||||
return 1;
|
||||
if (strncmp(spt, "cd", e) == 0) /* SCSI CD drive might be writeable. */
|
||||
return 1;
|
||||
if (strncmp(spt, "ad", e) == 0) /* IDE hard drive */
|
||||
return 1;
|
||||
if (strncmp(spt, "acd", e) == 0) /* IDE CD drive might be writeable */
|
||||
return 1;
|
||||
if (strncmp(spt, "fd", e) == 0) /* Floppy disk */
|
||||
return 1;
|
||||
if (strncmp(spt, "fla", e) == 0) /* Flash drive */
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/* ts A70909 */
|
||||
/** Estimate the potential payload capacity of a file address.
|
||||
@param path The address of the file to be examined. If it does not
|
||||
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 = NULL, *cpt;
|
||||
long blocks;
|
||||
off_t add_size = 0;
|
||||
int fd, ret;
|
||||
|
||||
BURN_ALLOC_MEM(testpath, char, 4096);
|
||||
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)
|
||||
{ret = -1; goto ex;}
|
||||
|
||||
#ifdef Libburn_if_this_was_linuX
|
||||
|
||||
} else if(S_ISBLK(stbuf.st_mode)) {
|
||||
int open_mode = O_RDWR, fd, ret;
|
||||
|
||||
if(burn_sg_open_o_excl)
|
||||
open_mode |= O_EXCL;
|
||||
fd = open(path, open_mode);
|
||||
if (fd == -1)
|
||||
{ret = -2; goto ex;}
|
||||
ret = ioctl(fd, BLKGETSIZE, &blocks);
|
||||
close(fd);
|
||||
if (ret == -1)
|
||||
{ret = -2; goto ex;}
|
||||
*bytes = ((off_t) blocks) * (off_t) 512;
|
||||
|
||||
#endif /* Libburn_if_this_was_linuX */
|
||||
|
||||
|
||||
} else if(S_ISCHR(stbuf.st_mode)) {
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd == -1)
|
||||
{ret = -2; goto ex;}
|
||||
ret = ioctl(fd, DIOCGMEDIASIZE, &add_size);
|
||||
close(fd);
|
||||
if (ret == -1)
|
||||
{ret = -2; goto ex;}
|
||||
*bytes = add_size;
|
||||
} else if(S_ISREG(stbuf.st_mode)) {
|
||||
add_size = stbuf.st_blocks * (off_t) 512;
|
||||
strcpy(testpath, path);
|
||||
} else
|
||||
{ret = 0; goto ex;}
|
||||
|
||||
if (testpath[0]) {
|
||||
if (statvfs(testpath, &vfsbuf) == -1)
|
||||
{ret = -2; goto ex;}
|
||||
*bytes = add_size + ((off_t) vfsbuf.f_frsize) *
|
||||
(off_t) vfsbuf.f_bavail;
|
||||
}
|
||||
ret = 1;
|
||||
ex:
|
||||
BURN_FREE_MEM(testpath);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* ts A91122 : an interface to open(O_DIRECT) or similar OS tricks. */
|
||||
|
||||
#ifdef Libburn_read_o_direcT
|
||||
|
||||
/* No special O_DIRECT-like precautions are implemented here */
|
||||
|
||||
#endif /* Libburn_read_o_direcT */
|
||||
|
||||
|
||||
int burn_os_open_track_src(char *path, int open_flags, int flag)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open(path, open_flags);
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
void *burn_os_alloc_buffer(size_t amount, int flag)
|
||||
{
|
||||
void *buf = NULL;
|
||||
|
||||
buf = calloc(1, amount);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
int burn_os_free_buffer(void *buffer, size_t amount, int flag)
|
||||
{
|
||||
if (buffer == NULL)
|
||||
return 0;
|
||||
free(buffer);
|
||||
return 1;
|
||||
}
|
||||
|
1092
libburn/sg-freebsd.c
1092
libburn/sg-freebsd.c
File diff suppressed because it is too large
Load Diff
995
libburn/sg-libcdio.c
Normal file
995
libburn/sg-libcdio.c
Normal file
@ -0,0 +1,995 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
/*
|
||||
Copyright (c) 2009 - 2011 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
|
||||
This is the main operating system dependent SCSI part of libburn. It implements
|
||||
the transport level aspects of SCSI control and command i/o.
|
||||
|
||||
Present implementation: GNU libcdio , for X/Open compliant operating systems
|
||||
|
||||
|
||||
PORTING:
|
||||
|
||||
Porting libburn typically will consist of adding a new operating system case
|
||||
to the following switcher files:
|
||||
os.h Operating system specific libburn definitions and declarations.
|
||||
sg.c Operating system dependent transport level modules.
|
||||
and of deriving the following system specific files from existing examples:
|
||||
os-*.h Included by os.h. You will need some general system knowledge
|
||||
about signals and knowledge about the storage object needs of your
|
||||
transport level module sg-*.c.
|
||||
|
||||
sg-*.c This source module. You will need special system knowledge about
|
||||
how to detect all potentially available drives, how to open them,
|
||||
eventually how to exclusively reserve them, how to perform
|
||||
SCSI transactions, how to inquire the (pseudo-)SCSI driver.
|
||||
You will not need to care about CD burning, MMC or other high-level
|
||||
SCSI aspects.
|
||||
|
||||
Said sg-*.c operations are defined by a public function interface, which has
|
||||
to be implemented in a way that provides libburn with the desired services:
|
||||
|
||||
sg_id_string() returns an id string of the SCSI transport adapter.
|
||||
It may be called before initialization but then may
|
||||
return only a preliminary id.
|
||||
|
||||
sg_initialize() performs global initialization of the SCSI transport
|
||||
adapter and eventually needed operating system
|
||||
facilities. Checks for compatibility of supporting
|
||||
software components.
|
||||
|
||||
sg_shutdown() performs global finalizations and releases golbally
|
||||
aquired resources.
|
||||
|
||||
sg_give_next_adr() iterates over the set of potentially useful drive
|
||||
address strings.
|
||||
|
||||
scsi_enumerate_drives() brings all available, not-whitelist-banned, and
|
||||
accessible drives into libburn's list of drives.
|
||||
|
||||
sg_dispose_drive() finalizes adapter specifics of struct burn_drive
|
||||
on destruction. Releases resources which were aquired
|
||||
underneath scsi_enumerate_drives().
|
||||
|
||||
sg_drive_is_open() tells wether libburn has the given drive in use.
|
||||
|
||||
sg_grab() opens the drive for SCSI commands and ensures
|
||||
undisturbed access.
|
||||
|
||||
sg_release() closes a drive opened by sg_grab()
|
||||
|
||||
sg_issue_command() sends a SCSI command to the drive, receives reply,
|
||||
and evaluates wether the command succeeded or shall
|
||||
be retried or finally failed.
|
||||
|
||||
sg_obtain_scsi_adr() tries to obtain SCSI address parameters.
|
||||
|
||||
|
||||
burn_os_is_2k_seekrw() tells whether the given path leads to a file object
|
||||
that can be used in 2 kB granularity by lseek(2),
|
||||
read(2), and possibly write(2) if not read-only..
|
||||
E.g. a USB stick or a hard disk.
|
||||
|
||||
burn_os_stdio_capacity() estimates the emulated media space of stdio-drives.
|
||||
|
||||
burn_os_open_track_src() opens a disk file in a way that allows best
|
||||
throughput with file reading and/or SCSI write command
|
||||
transmission.
|
||||
|
||||
burn_os_alloc_buffer() allocates a memory area that is suitable for file
|
||||
descriptors issued by burn_os_open_track_src().
|
||||
The buffer size may be rounded up for alignment
|
||||
reasons.
|
||||
|
||||
burn_os_free_buffer() delete a buffer obtained by burn_os_alloc_buffer().
|
||||
|
||||
Porting hints are marked by the text "PORTING:".
|
||||
Send feedback to libburn-hackers@pykix.org .
|
||||
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
|
||||
/** PORTING : ------- OS dependent headers and definitions ------ */
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef Libburn_os_has_statvfS
|
||||
#include <sys/statvfs.h>
|
||||
#endif /* Libburn_os_has_stavtfS */
|
||||
|
||||
#ifdef __linux
|
||||
/* for ioctl(BLKGETSIZE) */
|
||||
#include <sys/ioctl.h>
|
||||
#include <linux/fs.h>
|
||||
#endif
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#define Libburn_is_on_freebsD 1
|
||||
#endif
|
||||
#ifdef __FreeBSD_kernel__
|
||||
#define Libburn_is_on_freebsD 1
|
||||
#endif
|
||||
#ifdef Libburn_is_on_freebsD
|
||||
/* To avoid ATAPI devices */
|
||||
#define Libburn_guess_freebsd_atapi_devicE 1
|
||||
/* To obtain size of disk-like devices */
|
||||
#include <sys/disk.h> /* DIOCGMEDIASIZE */
|
||||
#endif /* Libburn_is_on_freebsD */
|
||||
|
||||
#define Libburn_guess_freebsd_atapi_devicE 1
|
||||
|
||||
#ifdef sun
|
||||
#define Libburn_is_on_solariS 1
|
||||
#endif
|
||||
#ifdef __sun
|
||||
#define Libburn_is_on_solariS 1
|
||||
#endif
|
||||
|
||||
#include <cdio/cdio.h>
|
||||
#include <cdio/logging.h>
|
||||
#include <cdio/mmc.h>
|
||||
|
||||
|
||||
/* The waiting time before eventually retrying a failed SCSI command.
|
||||
Before each retry wait Libburn_sg_linux_retry_incR longer than with
|
||||
the previous one.
|
||||
*/
|
||||
#define Libburn_sg_libcdio_retry_usleeP 100000
|
||||
#define Libburn_sg_libcdio_retry_incR 100000
|
||||
|
||||
|
||||
/** PORTING : ------ libburn portable headers and definitions ----- */
|
||||
|
||||
#include "transport.h"
|
||||
#include "drive.h"
|
||||
#include "sg.h"
|
||||
#include "spc.h"
|
||||
/* collides with symbols of <cdio/mmc.h>
|
||||
#include "mmc.h"
|
||||
*/
|
||||
#include "sbc.h"
|
||||
#include "debug.h"
|
||||
#include "toc.h"
|
||||
#include "util.h"
|
||||
#include "init.h"
|
||||
|
||||
#include "libdax_msgs.h"
|
||||
extern struct libdax_msgs *libdax_messenger;
|
||||
|
||||
|
||||
/* is in portable part of libburn */
|
||||
int burn_drive_is_banned(char *device_address);
|
||||
int burn_drive_resolve_link(char *path, char adr[],
|
||||
int *recursion_count, int flag); /* drive.c */
|
||||
|
||||
/* Whether to log SCSI commands:
|
||||
bit0= log in /tmp/libburn_sg_command_log
|
||||
bit1= log to stderr
|
||||
bit2= flush every line
|
||||
*/
|
||||
extern int burn_sg_log_scsi;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* PORTING: Private definitions. Port only if needed by public functions. */
|
||||
/* (Public functions are listed below) */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
|
||||
/* Storage object is in libburn/init.c
|
||||
whether to strive for exclusive access to the drive
|
||||
*/
|
||||
extern int burn_sg_open_o_excl;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* PORTING: Private functions. Port only if needed by public functions */
|
||||
/* (Public functions are listed below) */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
|
||||
static int sg_close_drive(struct burn_drive * d)
|
||||
{
|
||||
CdIo_t *p_cdio;
|
||||
|
||||
if (d->p_cdio != NULL) {
|
||||
p_cdio = (CdIo_t *) d->p_cdio;
|
||||
cdio_destroy(p_cdio);
|
||||
d->p_cdio = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int sg_give_next_adr_raw(burn_drive_enumerator_t *idx,
|
||||
char adr[], int adr_size, int initialize)
|
||||
{
|
||||
char **pos;
|
||||
int count = 0;
|
||||
|
||||
if (initialize == 1) {
|
||||
idx->pos = idx->ppsz_cd_drives =
|
||||
cdio_get_devices(DRIVER_DEVICE);
|
||||
if (idx->ppsz_cd_drives == NULL)
|
||||
return 0;
|
||||
|
||||
for (pos = idx->ppsz_cd_drives ; pos != NULL; pos++) {
|
||||
if (*pos == NULL)
|
||||
break;
|
||||
count++;
|
||||
}
|
||||
|
||||
} else if (initialize == -1) {
|
||||
if (idx->ppsz_cd_drives != NULL)
|
||||
if (*(idx->ppsz_cd_drives) != NULL)
|
||||
cdio_free_device_list(idx->ppsz_cd_drives);
|
||||
idx->ppsz_cd_drives = NULL;
|
||||
}
|
||||
|
||||
#ifdef Libburn_guess_freebsd_atapi_devicE
|
||||
try_next:;
|
||||
#endif
|
||||
|
||||
if (idx->pos == NULL)
|
||||
return 0;
|
||||
if (*(idx->pos) == NULL)
|
||||
return 0;
|
||||
|
||||
#ifdef Libburn_guess_freebsd_atapi_devicE
|
||||
if (strncmp(*(idx->pos), "/dev/acd", 8) == 0) {
|
||||
(idx->pos)++;
|
||||
goto try_next;
|
||||
}
|
||||
#endif
|
||||
|
||||
if (strlen(*(idx->pos)) >= adr_size)
|
||||
return -1;
|
||||
strcpy(adr, *(idx->pos));
|
||||
(idx->pos)++;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* PORTING: Private functions which contain publicly needed functionality. */
|
||||
/* Their portable part must be performed. So it is probably best */
|
||||
/* to replace the non-portable part and to call these functions */
|
||||
/* in your port, too. */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
|
||||
/** Wraps a detected drive into libburn structures and hands it over to
|
||||
libburn drive list.
|
||||
*/
|
||||
static void enumerate_common(char *fname, char *cdio_name,
|
||||
int bus_no, int host_no,
|
||||
int channel_no, int target_no, int lun_no)
|
||||
{
|
||||
int ret;
|
||||
struct burn_drive out;
|
||||
|
||||
/* General libburn drive setup */
|
||||
burn_setup_drive(&out, fname);
|
||||
|
||||
/* This transport adapter uses SCSI-family commands and models
|
||||
(seems the adapter would know better than its boss, if ever) */
|
||||
ret = burn_scsi_setup_drive(&out, bus_no, host_no, channel_no,
|
||||
target_no, lun_no, 0);
|
||||
if (ret <= 0)
|
||||
return;
|
||||
|
||||
/* PORTING: ------------------- non portable part --------------- */
|
||||
|
||||
/* Transport adapter is libcdio */
|
||||
/* Adapter specific handles and data */
|
||||
out.p_cdio = NULL;
|
||||
strcpy(out.libcdio_name, fname);
|
||||
if (strlen(cdio_name) < sizeof(out.libcdio_name))
|
||||
strcpy(out.libcdio_name, cdio_name);
|
||||
|
||||
/* PORTING: ---------------- end of non portable part ------------ */
|
||||
|
||||
/* Adapter specific functions with standardized names */
|
||||
out.grab = sg_grab;
|
||||
out.release = sg_release;
|
||||
out.drive_is_open = sg_drive_is_open;
|
||||
out.issue_command = sg_issue_command;
|
||||
/* Finally register drive and inquire drive information */
|
||||
burn_drive_finish_enum(&out);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* PORTING: Public functions. These MUST be ported. */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
|
||||
/** Returns the id string of the SCSI transport adapter and eventually
|
||||
needed operating system facilities.
|
||||
This call is usable even if sg_initialize() was not called yet. In that
|
||||
case a preliminary constant message might be issued if detailed info is
|
||||
not available yet.
|
||||
@param msg returns id string
|
||||
@param flag unused yet, submit 0
|
||||
@return 1 = success, <=0 = failure
|
||||
*/
|
||||
int sg_id_string(char msg[1024], int flag)
|
||||
{
|
||||
char *version_text;
|
||||
|
||||
sprintf(msg, "sg-libcdio h%d with libcdio ", LIBCDIO_VERSION_NUM);
|
||||
|
||||
#if LIBCDIO_VERSION_NUM < 83
|
||||
|
||||
LIBBURN_MISCONFIGURATION = 0;
|
||||
INTENTIONAL_ABORT_OF_COMPILATION__HEADERFILE_cdio_version_dot_h_TOO_OLD__NEED_libcdio_VERSION_NUM_83 = 0;
|
||||
LIBBURN_MISCONFIGURATION_ = 0;
|
||||
|
||||
#endif /* LIBCDIO_VERSION_NUM < 83 */
|
||||
|
||||
version_text = (char *) cdio_version_string;
|
||||
strncat(msg, version_text, 800);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/** Performs global initialization of the SCSI transport adapter and eventually
|
||||
needed operating system facilities. Checks for compatibility of supporting
|
||||
software components.
|
||||
@param msg returns ids and/or error messages of eventual helpers
|
||||
@param flag unused yet, submit 0
|
||||
@return 1 = success, <=0 = failure
|
||||
*/
|
||||
int sg_initialize(char msg[1024], int flag)
|
||||
{
|
||||
int cdio_ver;
|
||||
char *msg_pt;
|
||||
|
||||
cdio_loglevel_default = CDIO_LOG_ASSERT;
|
||||
|
||||
msg[0] = 0;
|
||||
sg_id_string(msg, 0);
|
||||
cdio_ver = libcdio_version_num;
|
||||
libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
|
||||
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
|
||||
msg , 0, 0);
|
||||
if (cdio_ver < LIBCDIO_VERSION_NUM) {
|
||||
strcat(msg, " ---> ");
|
||||
msg_pt = msg + strlen(msg);
|
||||
sprintf(msg_pt,
|
||||
"libcdio TOO OLD: numeric version %d , need at least %d",
|
||||
cdio_ver, LIBCDIO_VERSION_NUM);
|
||||
libdax_msgs_submit(libdax_messenger, -1,
|
||||
0x00000002,
|
||||
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
|
||||
msg_pt, 0, 0);
|
||||
return 0;
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/** Performs global finalization of the SCSI transport adapter and eventually
|
||||
needed operating system facilities. Releases globally aquired resources.
|
||||
@param flag unused yet, submit 0
|
||||
@return 1 = success, <=0 = failure
|
||||
*/
|
||||
int sg_shutdown(int flag)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
|
||||
struct burn_drive which are defined in os-*.h.
|
||||
The eventual initialization of those components was made underneath
|
||||
scsi_enumerate_drives().
|
||||
This will be called when a burn_drive gets disposed.
|
||||
@param d the drive to be finalized
|
||||
@param flag unused yet, submit 0
|
||||
@return 1 = success, <=0 = failure
|
||||
*/
|
||||
int sg_dispose_drive(struct burn_drive *d, int flag)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/** Returns the next index number and the next enumerated drive address.
|
||||
The enumeration has to cover all available and accessible drives. It is
|
||||
allowed to return addresses of drives which are not available but under
|
||||
some (even exotic) circumstances could be available. It is on the other
|
||||
hand allowed, only to hand out addresses which can really be used right
|
||||
in the moment of this call. (This implementation chooses the latter.)
|
||||
@param idx An opaque handle. Make no own theories about it.
|
||||
@param adr Takes the reply
|
||||
@param adr_size Gives maximum size of reply including final 0
|
||||
@param initialize 1 = start new,
|
||||
0 = continue, use no other values for now
|
||||
-1 = finish
|
||||
@return 1 = reply is a valid address , 0 = no further address available
|
||||
-1 = severe error (e.g. adr_size too small)
|
||||
*/
|
||||
int sg_give_next_adr(burn_drive_enumerator_t *idx,
|
||||
char adr[], int adr_size, int initialize)
|
||||
{
|
||||
int ret, recursion_count = 0, path_size = 4096;
|
||||
char *path = NULL;
|
||||
#ifdef Libburn_is_on_solariS
|
||||
int l;
|
||||
#endif
|
||||
BURN_ALLOC_MEM(path, char, path_size);
|
||||
|
||||
ret = sg_give_next_adr_raw(idx, adr, adr_size, initialize);
|
||||
if (ret <= 0)
|
||||
goto ex;
|
||||
if (strlen(adr) >= path_size)
|
||||
goto ex;
|
||||
|
||||
#ifdef Libburn_is_on_solariS
|
||||
/* >>> provisory : preserve Solaris /dev/rdsk/cXtYdZs2 addresses */
|
||||
l = strlen(adr);
|
||||
if (l >= 18)
|
||||
if (strncmp(adr, "/dev/rdsk/c", 11) == 0 && adr[11] >= '0' &&
|
||||
adr[11] <= '9' && strcmp(adr + (l - 2), "s2") == 0)
|
||||
{ret = 1; goto ex;}
|
||||
#endif /* Libburn_is_on_solariS */
|
||||
|
||||
ret = burn_drive_resolve_link(adr, path, &recursion_count, 2);
|
||||
if(ret > 0 && strlen(path) < adr_size)
|
||||
strcpy(path, adr);
|
||||
ret = (ret >= 0);
|
||||
ex:
|
||||
BURN_FREE_MEM(path);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** Brings all available, not-whitelist-banned, and accessible drives into
|
||||
libburn's list of drives.
|
||||
*/
|
||||
int scsi_enumerate_drives(void)
|
||||
{
|
||||
burn_drive_enumerator_t idx;
|
||||
int initialize = 1, ret, i_bus_no = -1, recursion_count = 0;
|
||||
int i_host_no = -1, i_channel_no = -1, i_target_no = -1, i_lun_no = -1;
|
||||
int buf_size = 4096;
|
||||
char *buf = NULL, *target = NULL;
|
||||
#ifdef Libburn_is_on_solariS
|
||||
int l;
|
||||
#endif
|
||||
|
||||
BURN_ALLOC_MEM(buf, char, buf_size);
|
||||
BURN_ALLOC_MEM(target, char, buf_size);
|
||||
|
||||
while(1) {
|
||||
ret = sg_give_next_adr_raw(&idx, buf, buf_size, initialize);
|
||||
initialize = 0;
|
||||
if (ret <= 0)
|
||||
break;
|
||||
ret = 1;
|
||||
|
||||
#ifdef Libburn_is_on_solariS
|
||||
/* >>> provisory : preserve Solaris /dev/rdsk/cXtYdZs2 */
|
||||
l = strlen(buf);
|
||||
if (l >= 18)
|
||||
if (strncmp(buf, "/dev/rdsk/c", 11) == 0 &&
|
||||
buf[11] >= '0' && buf[11] <= '9' &&
|
||||
strcmp(buf + (l - 2), "s2") == 0)
|
||||
ret = 0;
|
||||
#endif /* Libburn_is_on_solariS */
|
||||
|
||||
if (ret == 1) {
|
||||
ret = burn_drive_resolve_link(buf, target,
|
||||
&recursion_count,2);
|
||||
}
|
||||
if (ret <= 0)
|
||||
strcpy(target, buf);
|
||||
if (burn_drive_is_banned(target))
|
||||
continue;
|
||||
sg_obtain_scsi_adr(buf, &i_bus_no, &i_host_no,
|
||||
&i_channel_no, &i_target_no, &i_lun_no);
|
||||
enumerate_common(target, buf,
|
||||
i_bus_no, i_host_no, i_channel_no,
|
||||
i_target_no, i_lun_no);
|
||||
}
|
||||
sg_give_next_adr(&idx, buf, buf_size, -1);
|
||||
ret = 1;
|
||||
ex:;
|
||||
BURN_FREE_MEM(buf);
|
||||
BURN_FREE_MEM(target);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** Tells whether libburn has the given drive in use or exclusively reserved.
|
||||
If it is "open" then libburn will eventually call sg_release() on it when
|
||||
it is time to give up usage resp. reservation.
|
||||
*/
|
||||
/** Published as burn_drive.drive_is_open() */
|
||||
int sg_drive_is_open(struct burn_drive * d)
|
||||
{
|
||||
return (d->p_cdio != NULL);
|
||||
}
|
||||
|
||||
|
||||
/** Opens the drive for SCSI commands and - if burn activities are prone
|
||||
to external interference on your system - obtains an exclusive access lock
|
||||
on the drive. (Note: this is not physical tray locking.)
|
||||
A drive that has been opened with sg_grab() will eventually be handed
|
||||
over to sg_release() for closing and unreserving.
|
||||
*/
|
||||
int sg_grab(struct burn_drive *d)
|
||||
{
|
||||
CdIo_t *p_cdio;
|
||||
char *am_eff, *msg = NULL, *am_wanted;
|
||||
int os_errno, second_try = 0, ret;
|
||||
|
||||
if (d->p_cdio != NULL) {
|
||||
d->released = 0;
|
||||
{ret = 1; goto ex;}
|
||||
}
|
||||
if (d->libcdio_name[0] == 0) /* just to be sure it is initialized */
|
||||
strcpy(d->libcdio_name, d->devname);
|
||||
am_wanted = (burn_sg_open_o_excl & 63) ? "MMC_RDWR_EXCL" : "MMC_RDWR";
|
||||
try_to_open:;
|
||||
p_cdio = cdio_open_am(d->libcdio_name, DRIVER_DEVICE, am_wanted);
|
||||
if (p_cdio == NULL) {
|
||||
BURN_ALLOC_MEM(msg, char, 4096);
|
||||
os_errno = errno;
|
||||
sprintf(msg, "Could not grab drive '%s'", d->devname);
|
||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||
0x00020003,
|
||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||
msg, os_errno, 0);
|
||||
{ret = 0; goto ex;}
|
||||
}
|
||||
am_eff = (char *) cdio_get_arg(p_cdio, "access-mode");
|
||||
if (strncmp(am_eff, "MMC_RDWR", 8) != 0) {
|
||||
cdio_destroy(p_cdio);
|
||||
if (!second_try) {
|
||||
am_wanted = (burn_sg_open_o_excl & 63) ?
|
||||
"MMC_RDWR" : "MMC_RDWR_EXCL";
|
||||
second_try = 1;
|
||||
goto try_to_open;
|
||||
}
|
||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||
0x00020003,
|
||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"libcdio provides no MMC_RDWR access mode", 0, 0);
|
||||
{ret = 0; goto ex;}
|
||||
}
|
||||
|
||||
d->p_cdio = p_cdio;
|
||||
d->released = 0;
|
||||
ret = 1;
|
||||
ex:;
|
||||
BURN_FREE_MEM(msg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** PORTING: Is mainly about the call to sg_close_drive() and whether it
|
||||
implements the demanded functionality.
|
||||
*/
|
||||
/** Gives up the drive for SCSI commands and releases eventual access locks.
|
||||
(Note: this is not physical tray locking.)
|
||||
*/
|
||||
int sg_release(struct burn_drive *d)
|
||||
{
|
||||
if (d->p_cdio == NULL) {
|
||||
burn_print(1, "release an ungrabbed drive. die\n");
|
||||
return 0;
|
||||
}
|
||||
sg_close_drive(d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** Sends a SCSI command to the drive, receives reply and evaluates wether
|
||||
the command succeeded or shall be retried or finally failed.
|
||||
Returned SCSI errors shall not lead to a return value indicating failure.
|
||||
The callers get notified by c->error. An SCSI failure which leads not to
|
||||
a retry shall be notified via scsi_notify_error().
|
||||
The Libburn_log_sg_commandS facility might be of help when problems with
|
||||
a drive have to be examined. It shall stay disabled for normal use.
|
||||
@return: 1 success , <=0 failure
|
||||
*/
|
||||
int sg_issue_command(struct burn_drive *d, struct command *c)
|
||||
{
|
||||
int sense_valid = 0, i, timeout_ms, no_retry = 0;
|
||||
int key = 0, asc = 0, ascq = 0, done = 0;
|
||||
time_t start_time;
|
||||
driver_return_code_t i_status;
|
||||
unsigned int dxfer_len;
|
||||
static FILE *fp = NULL;
|
||||
mmc_cdb_t cdb = {{0, }};
|
||||
cdio_mmc_direction_t e_direction;
|
||||
CdIo_t *p_cdio;
|
||||
unsigned char *sense_pt = NULL;
|
||||
|
||||
c->error = 0;
|
||||
if (d->p_cdio == NULL) {
|
||||
return 0;
|
||||
}
|
||||
p_cdio = (CdIo_t *) d->p_cdio;
|
||||
if (burn_sg_log_scsi & 1) {
|
||||
if (fp == NULL) {
|
||||
fp= fopen("/tmp/libburn_sg_command_log", "a");
|
||||
fprintf(fp,
|
||||
"\n-----------------------------------------\n");
|
||||
}
|
||||
}
|
||||
if (burn_sg_log_scsi & 3)
|
||||
scsi_log_cmd(c,fp,0);
|
||||
|
||||
memcpy(cdb.field, c->opcode, c->oplen);
|
||||
if (c->dir == TO_DRIVE) {
|
||||
dxfer_len = c->page->bytes;
|
||||
e_direction = SCSI_MMC_DATA_WRITE;
|
||||
} else if (c->dir == FROM_DRIVE) {
|
||||
if (c->dxfer_len >= 0)
|
||||
dxfer_len = c->dxfer_len;
|
||||
else
|
||||
dxfer_len = BUFFER_SIZE;
|
||||
e_direction = SCSI_MMC_DATA_READ;
|
||||
/* touch page so we can use valgrind */
|
||||
memset(c->page->data, 0, BUFFER_SIZE);
|
||||
} else {
|
||||
dxfer_len = 0;
|
||||
e_direction = SCSI_MMC_DATA_NONE;
|
||||
}
|
||||
|
||||
/* retry-loop */
|
||||
start_time = time(NULL);
|
||||
timeout_ms = 200000;
|
||||
for(i = 0; !done; i++) {
|
||||
|
||||
i_status = mmc_run_cmd(p_cdio, timeout_ms, &cdb, e_direction,
|
||||
dxfer_len, c->page->data);
|
||||
sense_valid = mmc_last_cmd_sense(p_cdio, &sense_pt);
|
||||
if (sense_valid >= 18) {
|
||||
memcpy(c->sense, sense_pt,
|
||||
sense_valid >= sizeof(c->sense) ?
|
||||
sizeof(c->sense) : sense_valid );
|
||||
spc_decode_sense(c->sense, 0, &key, &asc, &ascq);
|
||||
} else
|
||||
key = asc = ascq = 0;
|
||||
if (sense_pt != NULL)
|
||||
free(sense_pt);
|
||||
|
||||
/* Regrettably mmc_run_cmd() does not clearly distinguish between transport
|
||||
failure and SCSI error reply.
|
||||
This reaction here would be for transport failure:
|
||||
|
||||
if (i_status != 0 && i_status != DRIVER_OP_ERROR) {
|
||||
libdax_msgs_submit(libdax_messenger,
|
||||
d->global_index, 0x0002010c,
|
||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Failed to transfer command to drive",
|
||||
errno, 0);
|
||||
sg_close_drive(d);
|
||||
d->released = 1;
|
||||
d->busy = BURN_DRIVE_IDLE;
|
||||
c->error = 1;
|
||||
return -1;
|
||||
}
|
||||
*/
|
||||
|
||||
if ((!sense_valid) || (key == 0 && asc == 0 && ascq == 0)) {
|
||||
memset(c->sense, 0, sizeof(c->sense));
|
||||
if (i_status != 0) { /* set dummy sense */
|
||||
/*LOGICAL UNIT NOT READY,
|
||||
CAUSE NOT REPORTABLE*/
|
||||
c->sense[0] = 0x70; /*Fixed format sense data*/
|
||||
c->sense[2] = 0x02;
|
||||
c->sense[12] = 0x04;
|
||||
no_retry = 1;
|
||||
}
|
||||
}
|
||||
if (i_status != 0 || (key || asc || ascq)) {
|
||||
done = scsi_eval_cmd_outcome(d, c, fp, c->sense, 18,
|
||||
0, start_time, timeout_ms, i, 2);
|
||||
} else
|
||||
done = 1;
|
||||
|
||||
} /* end of retry-loop */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/** Tries to obtain SCSI address parameters.
|
||||
@return 1 is success , 0 is failure
|
||||
*/
|
||||
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
|
||||
int *target_no, int *lun_no)
|
||||
{
|
||||
CdIo_t *p_cdio;
|
||||
char *tuple;
|
||||
|
||||
*bus_no = *host_no = *channel_no = *target_no = *lun_no = -1;
|
||||
|
||||
p_cdio = cdio_open(path, DRIVER_DEVICE);
|
||||
if (p_cdio == NULL)
|
||||
return 0;
|
||||
|
||||
/* Try whether a bus,host,channel,target,lun address tuple is
|
||||
available */
|
||||
tuple = (char *) cdio_get_arg(p_cdio, "scsi-tuple");
|
||||
if (tuple != NULL) if (tuple[0]) {
|
||||
sscanf(tuple, "%d,%d,%d,%d,%d",
|
||||
bus_no, host_no, channel_no, target_no, lun_no);
|
||||
}
|
||||
|
||||
cdio_destroy(p_cdio);
|
||||
return (*bus_no >= 0);
|
||||
}
|
||||
|
||||
|
||||
/** Tells wether a text is a persistent address as listed by the enumeration
|
||||
functions.
|
||||
*/
|
||||
int sg_is_enumerable_adr(char* adr)
|
||||
{
|
||||
burn_drive_enumerator_t idx;
|
||||
int initialize = 1, ret;
|
||||
char buf[64];
|
||||
|
||||
while(1) {
|
||||
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
|
||||
initialize = 0;
|
||||
if (ret <= 0)
|
||||
break;
|
||||
if (strcmp(adr, buf) == 0) {
|
||||
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
#define Libburn_guess_block_devicE 1
|
||||
#endif
|
||||
#ifdef __FreeBSD_kernel__
|
||||
#define Libburn_guess_block_devicE 1
|
||||
#endif
|
||||
|
||||
#ifdef Libburn_guess_block_devicE
|
||||
|
||||
/* ts B00115 */
|
||||
/* The FreeBSD implementation of burn_os_is_2k_seekrw().
|
||||
On FreeBSD there are no block devices.
|
||||
*/
|
||||
static int freebsd_is_2k_seekrw(char *path, int flag)
|
||||
{
|
||||
struct stat stbuf;
|
||||
char *spt;
|
||||
int i, e;
|
||||
|
||||
if (stat(path, &stbuf) == -1)
|
||||
return 0;
|
||||
if (S_ISREG(stbuf.st_mode))
|
||||
return 1;
|
||||
if (!S_ISCHR(stbuf.st_mode))
|
||||
return 0;
|
||||
spt = strrchr(path, '/');
|
||||
if (spt == NULL)
|
||||
spt = path;
|
||||
else
|
||||
spt++;
|
||||
e = strlen(spt);
|
||||
for (i = strlen(spt) - 1; i > 0; i--)
|
||||
if (spt[i] >= '0' && spt[i] <= '9')
|
||||
e = i;
|
||||
if (strncmp(spt, "da", e) == 0) /* SCSI disk. E.g. USB stick. */
|
||||
return 1;
|
||||
if (strncmp(spt, "cd", e) == 0) /* SCSI CD drive might be writeable. */
|
||||
return 1;
|
||||
if (strncmp(spt, "ad", e) == 0) /* IDE hard drive */
|
||||
return 1;
|
||||
if (strncmp(spt, "acd", e) == 0) /* IDE CD drive might be writeable */
|
||||
return 1;
|
||||
if (strncmp(spt, "fd", e) == 0) /* Floppy disk */
|
||||
return 1;
|
||||
if (strncmp(spt, "fla", e) == 0) /* Flash drive */
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
#endif /* Libburn_guess_block_devicE */
|
||||
|
||||
|
||||
/* Return 1 if the given path leads to a regular file or a device that can be
|
||||
seeked, read, and possibly written with 2 kB granularity.
|
||||
*/
|
||||
int burn_os_is_2k_seekrw(char *path, int flag)
|
||||
{
|
||||
#ifdef Libburn_guess_block_devicE
|
||||
return freebsd_is_2k_seekrw(path, flag);
|
||||
#else
|
||||
struct stat stbuf;
|
||||
|
||||
if (stat(path, &stbuf) == -1)
|
||||
return 0;
|
||||
if (S_ISREG(stbuf.st_mode))
|
||||
return 1;
|
||||
if (S_ISBLK(stbuf.st_mode))
|
||||
return 1;
|
||||
return 0;
|
||||
#endif /* ! Libburn_guess_block_devicE */
|
||||
}
|
||||
|
||||
|
||||
/** Estimate the potential payload capacity of a file address.
|
||||
@param path The address of the file to be examined. If it does not
|
||||
exist yet, then the directory will be inquired.
|
||||
@param bytes The pointed value gets modified, but only if an estimation is
|
||||
possible.
|
||||
@return -2 = cannot perform necessary operations on file object
|
||||
-1 = neither path nor dirname of path exist
|
||||
0 = could not estimate size capacity of file object
|
||||
1 = estimation has been made, bytes was set
|
||||
*/
|
||||
int burn_os_stdio_capacity(char *path, off_t *bytes)
|
||||
{
|
||||
struct stat stbuf;
|
||||
|
||||
#ifdef Libburn_os_has_statvfS
|
||||
struct statvfs vfsbuf;
|
||||
#endif
|
||||
|
||||
char *testpath = NULL, *cpt;
|
||||
long blocks;
|
||||
off_t add_size = 0;
|
||||
int ret;
|
||||
|
||||
BURN_ALLOC_MEM(testpath, char, 4096);
|
||||
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)
|
||||
{ret = -1; goto ex;}
|
||||
|
||||
#ifdef __linux
|
||||
|
||||
/* GNU/Linux specific determination of block device size */
|
||||
} else if(S_ISBLK(stbuf.st_mode)) {
|
||||
int open_mode = O_RDONLY, fd, ret;
|
||||
|
||||
fd = open(path, open_mode);
|
||||
if (fd == -1)
|
||||
{ret = -2; goto ex;}
|
||||
ret = ioctl(fd, BLKGETSIZE, &blocks);
|
||||
close(fd);
|
||||
if (ret == -1)
|
||||
{ret = -2; goto ex;}
|
||||
*bytes = ((off_t) blocks) * (off_t) 512;
|
||||
|
||||
#endif /* __linux */
|
||||
|
||||
#ifdef Libburn_is_on_freebsD
|
||||
|
||||
} else if(S_ISCHR(stbuf.st_mode)) {
|
||||
int fd, ret;
|
||||
|
||||
fd = open(path, O_RDONLY);
|
||||
if (fd == -1)
|
||||
{ret = -2; goto ex;}
|
||||
ret = ioctl(fd, DIOCGMEDIASIZE, &add_size);
|
||||
close(fd);
|
||||
if (ret == -1)
|
||||
{ret = -2; goto ex;}
|
||||
*bytes = add_size;
|
||||
|
||||
#endif /* Libburn_is_on_freebsD */
|
||||
|
||||
#ifdef Libburn_is_on_solariS
|
||||
|
||||
} else if(S_ISBLK(stbuf.st_mode)) {
|
||||
int open_mode = O_RDONLY, fd;
|
||||
|
||||
fd = open(path, open_mode);
|
||||
if (fd == -1)
|
||||
{ret = -2; goto ex;}
|
||||
*bytes = lseek(fd, 0, SEEK_END);
|
||||
close(fd);
|
||||
if (*bytes == -1) {
|
||||
*bytes = 0;
|
||||
{ret = 0; goto ex;}
|
||||
}
|
||||
|
||||
#endif /* Libburn_is_on_solariS */
|
||||
|
||||
} else if(S_ISREG(stbuf.st_mode)) {
|
||||
add_size = stbuf.st_blocks * (off_t) 512;
|
||||
strcpy(testpath, path);
|
||||
} else
|
||||
{ret = 0; goto ex;}
|
||||
|
||||
if (testpath[0]) {
|
||||
|
||||
#ifdef Libburn_os_has_statvfS
|
||||
|
||||
if (statvfs(testpath, &vfsbuf) == -1)
|
||||
{ret = -2; goto ex;}
|
||||
*bytes = add_size + ((off_t) vfsbuf.f_frsize) *
|
||||
(off_t) vfsbuf.f_bavail;
|
||||
|
||||
#else /* Libburn_os_has_statvfS */
|
||||
|
||||
{ret = 0; goto ex;}
|
||||
|
||||
#endif /* ! Libburn_os_has_stavtfS */
|
||||
|
||||
}
|
||||
ret = 1;
|
||||
ex:;
|
||||
BURN_FREE_MEM(testpath);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* ts A91122 : an interface to open(O_DIRECT) or similar OS tricks. */
|
||||
|
||||
#ifdef Libburn_read_o_direcT
|
||||
|
||||
/* No special O_DIRECT-like precautions are implemented here */
|
||||
|
||||
#endif /* Libburn_read_o_direcT */
|
||||
|
||||
|
||||
int burn_os_open_track_src(char *path, int open_flags, int flag)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open(path, open_flags);
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
void *burn_os_alloc_buffer(size_t amount, int flag)
|
||||
{
|
||||
void *buf = NULL;
|
||||
|
||||
buf = calloc(1, amount);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
int burn_os_free_buffer(void *buffer, size_t amount, int flag)
|
||||
{
|
||||
if (buffer == NULL)
|
||||
return 0;
|
||||
free(buffer);
|
||||
return 1;
|
||||
}
|
||||
|
2042
libburn/sg-linux.c
2042
libburn/sg-linux.c
File diff suppressed because it is too large
Load Diff
883
libburn/sg-solaris.c
Normal file
883
libburn/sg-solaris.c
Normal file
@ -0,0 +1,883 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
/*
|
||||
Copyright (c) 2010 - 2011 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
|
||||
/*
|
||||
|
||||
This is the main operating system dependent SCSI part of libburn. It implements
|
||||
the transport level aspects of SCSI control and command i/o.
|
||||
|
||||
Present implementation: Solaris uscsi, e.g. for SunOS 5.11
|
||||
|
||||
|
||||
PORTING:
|
||||
|
||||
Porting libburn typically will consist of adding a new operating system case
|
||||
to the following switcher files:
|
||||
os.h Operating system specific libburn definitions and declarations.
|
||||
sg.c Operating system dependent transport level modules.
|
||||
and of deriving the following system specific files from existing examples:
|
||||
os-*.h Included by os.h. You will need some general system knowledge
|
||||
about signals and knowledge about the storage object needs of your
|
||||
transport level module sg-*.c.
|
||||
|
||||
sg-*.c This source module. You will need special system knowledge about
|
||||
how to detect all potentially available drives, how to open them,
|
||||
eventually how to exclusively reserve them, how to perform
|
||||
SCSI transactions, how to inquire the (pseudo-)SCSI driver.
|
||||
You will not need to care about CD burning, MMC or other high-level
|
||||
SCSI aspects.
|
||||
|
||||
Said sg-*.c operations are defined by a public function interface, which has
|
||||
to be implemented in a way that provides libburn with the desired services:
|
||||
|
||||
sg_id_string() returns an id string of the SCSI transport adapter.
|
||||
It may be called before initialization but then may
|
||||
return only a preliminary id.
|
||||
|
||||
sg_initialize() performs global initialization of the SCSI transport
|
||||
adapter and eventually needed operating system
|
||||
facilities. Checks for compatibility of supporting
|
||||
software components.
|
||||
|
||||
sg_shutdown() performs global finalizations and releases golbally
|
||||
aquired resources.
|
||||
|
||||
sg_give_next_adr() iterates over the set of potentially useful drive
|
||||
address strings.
|
||||
|
||||
scsi_enumerate_drives() brings all available, not-whitelist-banned, and
|
||||
accessible drives into libburn's list of drives.
|
||||
|
||||
sg_dispose_drive() finalizes adapter specifics of struct burn_drive
|
||||
on destruction. Releases resources which were aquired
|
||||
underneath scsi_enumerate_drives().
|
||||
|
||||
sg_drive_is_open() tells wether libburn has the given drive in use.
|
||||
|
||||
sg_grab() opens the drive for SCSI commands and ensures
|
||||
undisturbed access.
|
||||
|
||||
sg_release() closes a drive opened by sg_grab()
|
||||
|
||||
sg_issue_command() sends a SCSI command to the drive, receives reply,
|
||||
and evaluates wether the command succeeded or shall
|
||||
be retried or finally failed.
|
||||
|
||||
sg_obtain_scsi_adr() tries to obtain SCSI address parameters.
|
||||
|
||||
|
||||
burn_os_is_2k_seekrw() tells whether the given path leads to a file object
|
||||
that can be used in 2 kB granularity by lseek(2),
|
||||
read(2), and possibly write(2) if not read-only..
|
||||
E.g. a USB stick or a hard disk.
|
||||
|
||||
burn_os_stdio_capacity() estimates the emulated media space of stdio-drives.
|
||||
|
||||
burn_os_open_track_src() opens a disk file in a way that allows best
|
||||
throughput with file reading and/or SCSI write command
|
||||
transmission.
|
||||
|
||||
burn_os_alloc_buffer() allocates a memory area that is suitable for file
|
||||
descriptors issued by burn_os_open_track_src().
|
||||
The buffer size may be rounded up for alignment
|
||||
reasons.
|
||||
|
||||
burn_os_free_buffer() delete a buffer obtained by burn_os_alloc_buffer().
|
||||
|
||||
Porting hints are marked by the text "PORTING:".
|
||||
Send feedback to libburn-hackers@pykix.org .
|
||||
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
|
||||
/** PORTING : ------- OS dependent headers and definitions ------ */
|
||||
|
||||
#include <unistd.h>
|
||||
#include <stropts.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/types.h>
|
||||
#include <errno.h>
|
||||
#include <fcntl.h>
|
||||
#include <sys/stat.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#ifdef Libburn_os_has_statvfS
|
||||
#include <sys/statvfs.h>
|
||||
#endif /* Libburn_os_has_stavtfS */
|
||||
|
||||
#include <sys/dkio.h>
|
||||
#include <sys/vtoc.h>
|
||||
|
||||
#include <sys/scsi/impl/uscsi.h>
|
||||
|
||||
|
||||
/* The waiting time before eventually retrying a failed SCSI command.
|
||||
Before each retry wait Libburn_sg_linux_retry_incR longer than with
|
||||
the previous one.
|
||||
*/
|
||||
#define Libburn_sg_solaris_retry_usleeP 100000
|
||||
#define Libburn_sg_solaris_retry_incR 100000
|
||||
|
||||
|
||||
/** PORTING : ------ libburn portable headers and definitions ----- */
|
||||
|
||||
#include "transport.h"
|
||||
#include "drive.h"
|
||||
#include "sg.h"
|
||||
#include "spc.h"
|
||||
#include "sbc.h"
|
||||
#include "debug.h"
|
||||
#include "toc.h"
|
||||
#include "util.h"
|
||||
#include "init.h"
|
||||
|
||||
#include "libdax_msgs.h"
|
||||
extern struct libdax_msgs *libdax_messenger;
|
||||
|
||||
|
||||
/* is in portable part of libburn */
|
||||
int burn_drive_is_banned(char *device_address);
|
||||
int burn_drive_resolve_link(char *path, char adr[],
|
||||
int *recursion_count, int flag); /* drive.c */
|
||||
|
||||
/* Whether to log SCSI commands:
|
||||
bit0= log in /tmp/libburn_sg_command_log
|
||||
bit1= log to stderr
|
||||
bit2= flush every line
|
||||
*/
|
||||
extern int burn_sg_log_scsi;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* PORTING: Private definitions. Port only if needed by public functions. */
|
||||
/* (Public functions are listed below) */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
|
||||
/* Storage object is in libburn/init.c
|
||||
whether to strive for exclusive access to the drive
|
||||
*/
|
||||
extern int burn_sg_open_o_excl;
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* PORTING: Private functions. Port only if needed by public functions */
|
||||
/* (Public functions are listed below) */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
|
||||
static int sg_close_drive(struct burn_drive * d)
|
||||
{
|
||||
if (d->fd != -1) {
|
||||
close(d->fd);
|
||||
d->fd = -1;
|
||||
return 1;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
static int decode_btl_number(char **cpt, int stopper, int *no)
|
||||
{
|
||||
*no = 0;
|
||||
for ((*cpt)++; **cpt != stopper; (*cpt)++) {
|
||||
if (**cpt < '0' || **cpt > '9')
|
||||
return 0;
|
||||
*no = *no * 10 + **cpt - '0';
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* Read bus, target, lun from name "cXtYdZs2".
|
||||
Return 0 if name is not of the desired form.
|
||||
*/
|
||||
static int decode_btl_solaris(char *name, int *busno, int *tgtno, int *lunno,
|
||||
int flag)
|
||||
{
|
||||
char *cpt;
|
||||
int ret;
|
||||
|
||||
*busno = *tgtno = *lunno = -1;
|
||||
cpt = name;
|
||||
if (*cpt != 'c')
|
||||
return 0;
|
||||
ret = decode_btl_number(&cpt, 't', busno);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
ret = decode_btl_number(&cpt, 'd', tgtno);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
ret = decode_btl_number(&cpt, 's', lunno);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
cpt++;
|
||||
if (*cpt != '2' || *(cpt + 1) != 0)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int start_enum_cXtYdZs2(burn_drive_enumerator_t *idx, int flag)
|
||||
{
|
||||
DIR *dir;
|
||||
|
||||
idx->dir = NULL;
|
||||
dir = opendir("/dev/rdsk");
|
||||
if (dir == NULL) {
|
||||
libdax_msgs_submit(libdax_messenger, -1,
|
||||
0x0002000c, LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Cannot start device file enumeration. opendir(\"/dev/rdsk\") failed.",
|
||||
errno, 0);
|
||||
return 0;
|
||||
}
|
||||
idx->dir = dir;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
static int next_enum_cXtYdZs2(burn_drive_enumerator_t *idx,
|
||||
char adr[], int adr_size, int flag)
|
||||
{
|
||||
int busno, tgtno, lunno, ret, fd = -1, volpath_size = 160;
|
||||
char *volpath = NULL;
|
||||
struct dirent *entry;
|
||||
struct dk_cinfo cinfo;
|
||||
DIR *dir;
|
||||
|
||||
BURN_ALLOC_MEM(volpath, char, volpath_size);
|
||||
|
||||
dir = idx->dir;
|
||||
while (1) {
|
||||
errno = 0;
|
||||
entry = readdir(dir);
|
||||
if (entry == NULL) {
|
||||
if (errno) {
|
||||
libdax_msgs_submit(libdax_messenger,
|
||||
-1, 0x0002000d,
|
||||
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
|
||||
"Cannot enumerate next device. readdir() from \"/dev/rdsk\" failed.",
|
||||
errno, 0);
|
||||
{ret = -1; goto ex;}
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (strlen(entry->d_name) > (size_t) (volpath_size - 11))
|
||||
continue;
|
||||
ret = decode_btl_solaris(entry->d_name,
|
||||
&busno, &tgtno, &lunno, 0);
|
||||
if (ret <= 0)
|
||||
continue; /* not cXtYdZs2 */
|
||||
|
||||
sprintf(volpath, "/dev/rdsk/%s", entry->d_name);
|
||||
if (burn_drive_is_banned(volpath))
|
||||
continue;
|
||||
|
||||
fd = open(volpath, O_RDONLY | O_NDELAY);
|
||||
if (fd < 0)
|
||||
continue;
|
||||
/* See man dkio */
|
||||
ret = ioctl(fd, DKIOCINFO, &cinfo);
|
||||
close(fd);
|
||||
if (ret < 0)
|
||||
continue;
|
||||
if (cinfo.dki_ctype != DKC_CDROM)
|
||||
continue;
|
||||
if (adr_size <= (int) strlen(volpath))
|
||||
{ret = -1; goto ex;}
|
||||
strcpy(adr, volpath);
|
||||
{ret = 1; goto ex;}
|
||||
}
|
||||
ret = 0;
|
||||
ex:;
|
||||
BURN_FREE_MEM(volpath);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
static int end_enum_cXtYdZs2(burn_drive_enumerator_t *idx, int flag)
|
||||
{
|
||||
DIR *dir;
|
||||
|
||||
dir = idx->dir;
|
||||
if(dir != NULL)
|
||||
closedir(dir);
|
||||
idx->dir = NULL;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* ----------------------------------------------------------------------- */
|
||||
/* PORTING: Private functions which contain publicly needed functionality. */
|
||||
/* Their portable part must be performed. So it is probably best */
|
||||
/* to replace the non-portable part and to call these functions */
|
||||
/* in your port, too. */
|
||||
/* ----------------------------------------------------------------------- */
|
||||
|
||||
|
||||
/** Wraps a detected drive into libburn structures and hands it over to
|
||||
libburn drive list.
|
||||
*/
|
||||
static void enumerate_common(char *fname,
|
||||
int bus_no, int host_no,
|
||||
int channel_no, int target_no, int lun_no)
|
||||
{
|
||||
int ret;
|
||||
struct burn_drive out;
|
||||
|
||||
/* General libburn drive setup */
|
||||
burn_setup_drive(&out, fname);
|
||||
|
||||
/* This transport adapter uses SCSI-family commands and models
|
||||
(seems the adapter would know better than its boss, if ever) */
|
||||
ret = burn_scsi_setup_drive(&out, bus_no, host_no, channel_no,
|
||||
target_no, lun_no, 0);
|
||||
if (ret <= 0)
|
||||
return;
|
||||
|
||||
/* PORTING: ------------------- non portable part --------------- */
|
||||
|
||||
/* Transport adapter is Solaris uscsi */
|
||||
/* Adapter specific handles and data */
|
||||
out.fd = -1;
|
||||
|
||||
/* PORTING: ---------------- end of non portable part ------------ */
|
||||
|
||||
/* Adapter specific functions with standardized names */
|
||||
out.grab = sg_grab;
|
||||
out.release = sg_release;
|
||||
out.drive_is_open = sg_drive_is_open;
|
||||
out.issue_command = sg_issue_command;
|
||||
/* Finally register drive and inquire drive information */
|
||||
burn_drive_finish_enum(&out);
|
||||
}
|
||||
|
||||
|
||||
/* ------------------------------------------------------------------------ */
|
||||
/* PORTING: Public functions. These MUST be ported. */
|
||||
/* ------------------------------------------------------------------------ */
|
||||
|
||||
|
||||
/** Returns the id string of the SCSI transport adapter and eventually
|
||||
needed operating system facilities.
|
||||
This call is usable even if sg_initialize() was not called yet. In that
|
||||
case a preliminary constant message might be issued if detailed info is
|
||||
not available yet.
|
||||
@param msg returns id string
|
||||
@param flag unused yet, submit 0
|
||||
@return 1 = success, <=0 = failure
|
||||
*/
|
||||
int sg_id_string(char msg[1024], int flag)
|
||||
{
|
||||
sprintf(msg, "internal Solaris uscsi adapter sg-solaris");
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/** Performs global initialization of the SCSI transport adapter and eventually
|
||||
needed operating system facilities. Checks for compatibility of supporting
|
||||
software components.
|
||||
@param msg returns ids and/or error messages of eventual helpers
|
||||
@param flag unused yet, submit 0
|
||||
@return 1 = success, <=0 = failure
|
||||
*/
|
||||
int sg_initialize(char msg[1024], int flag)
|
||||
{
|
||||
return sg_id_string(msg, 0);
|
||||
}
|
||||
|
||||
|
||||
/** Performs global finalization of the SCSI transport adapter and eventually
|
||||
needed operating system facilities. Releases globally aquired resources.
|
||||
@param flag unused yet, submit 0
|
||||
@return 1 = success, <=0 = failure
|
||||
*/
|
||||
int sg_shutdown(int flag)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
|
||||
struct burn_drive which are defined in os-*.h.
|
||||
The eventual initialization of those components was made underneath
|
||||
scsi_enumerate_drives().
|
||||
This will be called when a burn_drive gets disposed.
|
||||
@param d the drive to be finalized
|
||||
@param flag unused yet, submit 0
|
||||
@return 1 = success, <=0 = failure
|
||||
*/
|
||||
int sg_dispose_drive(struct burn_drive *d, int flag)
|
||||
{
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/** Returns the next index number and the next enumerated drive address.
|
||||
The enumeration has to cover all available and accessible drives. It is
|
||||
allowed to return addresses of drives which are not available but under
|
||||
some (even exotic) circumstances could be available. It is on the other
|
||||
hand allowed, only to hand out addresses which can really be used right
|
||||
in the moment of this call. (This implementation chooses the latter.)
|
||||
@param idx An opaque handle. Make no own theories about it.
|
||||
@param adr Takes the reply
|
||||
@param adr_size Gives maximum size of reply including final 0
|
||||
@param initialize 1 = start new,
|
||||
0 = continue, use no other values for now
|
||||
-1 = finish
|
||||
@return 1 = reply is a valid address , 0 = no further address available
|
||||
-1 = severe error (e.g. adr_size too small)
|
||||
*/
|
||||
int sg_give_next_adr(burn_drive_enumerator_t *idx,
|
||||
char adr[], int adr_size, int initialize)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (initialize == 1) {
|
||||
ret = start_enum_cXtYdZs2(idx, 0);
|
||||
if (ret <= 0)
|
||||
return ret;
|
||||
} else if (initialize == -1) {
|
||||
ret = end_enum_cXtYdZs2(idx, 0);
|
||||
return 0;
|
||||
}
|
||||
ret = next_enum_cXtYdZs2(idx, adr, adr_size, 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** Brings all available, not-whitelist-banned, and accessible drives into
|
||||
libburn's list of drives.
|
||||
*/
|
||||
int scsi_enumerate_drives(void)
|
||||
{
|
||||
burn_drive_enumerator_t idx;
|
||||
int initialize = 1, ret, i_bus_no = -1, buf_size = 4096;
|
||||
int i_host_no = -1, i_channel_no = -1, i_target_no = -1, i_lun_no = -1;
|
||||
char *buf = NULL;
|
||||
|
||||
BURN_ALLOC_MEM(buf, char, buf_size);
|
||||
|
||||
while(1) {
|
||||
ret = sg_give_next_adr(&idx, buf, buf_size, initialize);
|
||||
initialize = 0;
|
||||
if (ret <= 0)
|
||||
break;
|
||||
if (burn_drive_is_banned(buf))
|
||||
continue;
|
||||
sg_obtain_scsi_adr(buf, &i_bus_no, &i_host_no,
|
||||
&i_channel_no, &i_target_no, &i_lun_no);
|
||||
enumerate_common(buf,
|
||||
i_bus_no, i_host_no, i_channel_no,
|
||||
i_target_no, i_lun_no);
|
||||
}
|
||||
sg_give_next_adr(&idx, buf, buf_size, -1);
|
||||
ret = 1;
|
||||
ex:;
|
||||
BURN_FREE_MEM(buf);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** Tells whether libburn has the given drive in use or exclusively reserved.
|
||||
If it is "open" then libburn will eventually call sg_release() on it when
|
||||
it is time to give up usage resp. reservation.
|
||||
*/
|
||||
/** Published as burn_drive.drive_is_open() */
|
||||
int sg_drive_is_open(struct burn_drive * d)
|
||||
{
|
||||
return (d->fd != -1);
|
||||
}
|
||||
|
||||
|
||||
/** Opens the drive for SCSI commands and - if burn activities are prone
|
||||
to external interference on your system - obtains an exclusive access lock
|
||||
on the drive. (Note: this is not physical tray locking.)
|
||||
A drive that has been opened with sg_grab() will eventually be handed
|
||||
over to sg_release() for closing and unreserving.
|
||||
*/
|
||||
int sg_grab(struct burn_drive *d)
|
||||
{
|
||||
char *msg = NULL;
|
||||
int os_errno, ret;
|
||||
struct dk_cinfo cinfo;
|
||||
|
||||
BURN_ALLOC_MEM(msg, char, 4096);
|
||||
|
||||
if (d->fd != -1) {
|
||||
d->released = 0;
|
||||
{ret = 1; goto ex;}
|
||||
}
|
||||
d->fd = open(d->devname, O_RDONLY | O_NDELAY);
|
||||
if (d->fd == -1) {
|
||||
os_errno = errno;
|
||||
sprintf(msg, "Could not grab drive '%s'", d->devname);
|
||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||
0x00020003,
|
||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||
msg, os_errno, 0);
|
||||
{ret = 0; goto ex;}
|
||||
}
|
||||
ret = ioctl(d->fd, DKIOCINFO, &cinfo);
|
||||
if (ret < 0)
|
||||
goto revoke;
|
||||
if (cinfo.dki_ctype != DKC_CDROM)
|
||||
goto revoke;
|
||||
|
||||
/* >>> obtain eventual locks */;
|
||||
|
||||
d->released = 0;
|
||||
{ret = 1; goto ex;}
|
||||
revoke:;
|
||||
sprintf(msg, "Could not grab drive '%s'. Not a CDROM device.",
|
||||
d->devname);
|
||||
libdax_msgs_submit(libdax_messenger, d->global_index,
|
||||
0x00020003,
|
||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||
msg, 0, 0);
|
||||
ret = 0;
|
||||
ex:;
|
||||
BURN_FREE_MEM(msg);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/** PORTING: Is mainly about the call to sg_close_drive() and whether it
|
||||
implements the demanded functionality.
|
||||
*/
|
||||
/** Gives up the drive for SCSI commands and releases eventual access locks.
|
||||
(Note: this is not physical tray locking.)
|
||||
*/
|
||||
int sg_release(struct burn_drive *d)
|
||||
{
|
||||
if (d->fd < 0) {
|
||||
burn_print(1, "release an ungrabbed drive. die\n");
|
||||
return 0;
|
||||
}
|
||||
sg_close_drive(d);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** Sends a SCSI command to the drive, receives reply and evaluates wether
|
||||
the command succeeded or shall be retried or finally failed.
|
||||
Returned SCSI errors shall not lead to a return value indicating failure.
|
||||
The callers get notified by c->error. An SCSI failure which leads not to
|
||||
a retry shall be notified via scsi_notify_error().
|
||||
The Libburn_log_sg_commandS facility might be of help when problems with
|
||||
a drive have to be examined. It shall stay disabled for normal use.
|
||||
@return: 1 success , <=0 failure
|
||||
*/
|
||||
int sg_issue_command(struct burn_drive *d, struct command *c)
|
||||
{
|
||||
int i, timeout_ms, ret, key, asc, ascq, done = 0;
|
||||
time_t start_time;
|
||||
struct uscsi_cmd cgc;
|
||||
char msg[80];
|
||||
static FILE *fp = NULL;
|
||||
|
||||
c->error = 0;
|
||||
memset(c->sense, 0, sizeof(c->sense));
|
||||
if (d->fd == -1)
|
||||
return 0;
|
||||
|
||||
if (burn_sg_log_scsi & 1) {
|
||||
if (fp == NULL) {
|
||||
fp= fopen("/tmp/libburn_sg_command_log", "a");
|
||||
fprintf(fp,
|
||||
"\n-----------------------------------------\n");
|
||||
}
|
||||
}
|
||||
if (burn_sg_log_scsi & 3)
|
||||
scsi_log_cmd(c,fp,0);
|
||||
|
||||
memset (&cgc, 0, sizeof (struct uscsi_cmd));
|
||||
/* No error messages, no retries,
|
||||
do not execute with other commands, request sense data
|
||||
*/
|
||||
cgc.uscsi_flags = USCSI_SILENT | USCSI_DIAGNOSE | USCSI_ISOLATE
|
||||
| USCSI_RQENABLE;
|
||||
cgc.uscsi_timeout = 200;
|
||||
cgc.uscsi_cdb = (caddr_t) c->opcode;
|
||||
cgc.uscsi_bufaddr = (caddr_t) c->page->data;
|
||||
if (c->dir == TO_DRIVE) {
|
||||
cgc.uscsi_flags |= USCSI_WRITE;
|
||||
cgc.uscsi_buflen = c->page->bytes;
|
||||
} else if (c->dir == FROM_DRIVE) {
|
||||
cgc.uscsi_flags |= USCSI_READ;
|
||||
if (c->dxfer_len >= 0)
|
||||
cgc.uscsi_buflen = c->dxfer_len;
|
||||
else
|
||||
cgc.uscsi_buflen = BUFFER_SIZE;
|
||||
/* touch page so we can use valgrind */
|
||||
memset(c->page->data, 0, BUFFER_SIZE);
|
||||
} else {
|
||||
cgc.uscsi_buflen = 0;
|
||||
}
|
||||
cgc.uscsi_cdblen = c->oplen;
|
||||
cgc.uscsi_rqlen = sizeof(c->sense);
|
||||
cgc.uscsi_rqbuf = (caddr_t) c->sense;
|
||||
|
||||
/* retry-loop */
|
||||
start_time = time(NULL);
|
||||
timeout_ms = 200000;
|
||||
for(i = 0; !done; i++) {
|
||||
|
||||
ret = ioctl(d->fd, USCSICMD, &cgc);
|
||||
|
||||
/* For cgc.uscsi_status see SAM-3 5.3.1, Table 22
|
||||
0 = GOOD , 2 = CHECK CONDITION : Sense Data are delivered
|
||||
8 = BUSY
|
||||
*/
|
||||
if (ret != 0 && cgc.uscsi_status != 2) {
|
||||
sprintf(msg,
|
||||
"Failed to transfer command to drive. (uscsi_status = 0x%X)",
|
||||
(unsigned int) cgc.uscsi_status),
|
||||
libdax_msgs_submit(libdax_messenger,
|
||||
d->global_index, 0x0002010c,
|
||||
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
|
||||
msg, errno, 0);
|
||||
sg_close_drive(d);
|
||||
d->released = 1;
|
||||
d->busy = BURN_DRIVE_IDLE;
|
||||
c->error = 1;
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
||||
/* >>> Should replace "18" by realistic sense length.
|
||||
What's about following older remark ?
|
||||
*/
|
||||
/* >>> valid sense: cgc.uscsi_rqlen - cgc.uscsi_rqresid */;
|
||||
|
||||
spc_decode_sense(c->sense, 0, &key, &asc, &ascq);
|
||||
if (key || asc || ascq) {
|
||||
done = scsi_eval_cmd_outcome(d, c, fp, c->sense, 18, 0,
|
||||
start_time, timeout_ms, i, 2);
|
||||
} else
|
||||
done = 1;
|
||||
|
||||
} /* end of retry-loop */
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/** Tries to obtain SCSI address parameters.
|
||||
@return 1 is success , 0 is failure
|
||||
*/
|
||||
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
|
||||
int *target_no, int *lun_no)
|
||||
{
|
||||
int ret;
|
||||
|
||||
/* Try to guess from path */
|
||||
if (strncmp("/dev/rdsk/", path, 10) == 0) {
|
||||
ret = decode_btl_solaris(path + 10,
|
||||
bus_no, target_no, lun_no, 0);
|
||||
if (ret > 0) {
|
||||
*host_no = *bus_no;
|
||||
*channel_no = 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
*bus_no = *host_no = *channel_no = *target_no = *lun_no = -1;
|
||||
|
||||
/* >>> Could need a ioctl which gives SCSI numbers */;
|
||||
|
||||
return (0);
|
||||
}
|
||||
|
||||
|
||||
/** Tells wether a text is a persistent address as listed by the enumeration
|
||||
functions.
|
||||
*/
|
||||
|
||||
#ifndef NIX
|
||||
|
||||
int sg_is_enumerable_adr(char* path)
|
||||
{
|
||||
int ret;
|
||||
int bus_no, target_no, lun_no;
|
||||
struct stat stbuf;
|
||||
|
||||
if (strncmp("/dev/rdsk/", path, 10) != 0)
|
||||
return 0;
|
||||
ret = decode_btl_solaris(path + 10, &bus_no, &target_no, &lun_no, 0);
|
||||
if (ret <= 0)
|
||||
return 0;
|
||||
if (stat(path, &stbuf) == -1)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
#else /* ! NIX */
|
||||
|
||||
int sg_is_enumerable_adr(char* adr)
|
||||
{
|
||||
burn_drive_enumerator_t idx;
|
||||
int initialize = 1, ret;
|
||||
char buf[64];
|
||||
|
||||
while(1) {
|
||||
ret = sg_give_next_adr(&idx, buf, sizeof(buf), initialize);
|
||||
initialize = 0;
|
||||
if (ret <= 0)
|
||||
break;
|
||||
if (strcmp(adr, buf) == 0) {
|
||||
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
sg_give_next_adr(&idx, buf, sizeof(buf), -1);
|
||||
return (0);
|
||||
}
|
||||
#endif /* NIX */
|
||||
|
||||
|
||||
|
||||
|
||||
/* Return 1 if the given path leads to a regular file or a device that can be
|
||||
seeked, read, and possibly written with 2 kB granularity.
|
||||
*/
|
||||
int burn_os_is_2k_seekrw(char *path, int flag)
|
||||
{
|
||||
struct stat stbuf;
|
||||
|
||||
if (stat(path, &stbuf) == -1)
|
||||
return 0;
|
||||
if (S_ISREG(stbuf.st_mode))
|
||||
return 1;
|
||||
if (S_ISBLK(stbuf.st_mode))
|
||||
return 1;
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/** Estimate the potential payload capacity of a file address.
|
||||
@param path The address of the file to be examined. If it does not
|
||||
exist yet, then the directory will be inquired.
|
||||
@param bytes The pointed value gets modified, but only if an estimation is
|
||||
possible.
|
||||
@return -2 = cannot perform necessary operations on file object
|
||||
-1 = neither path nor dirname of path exist
|
||||
0 = could not estimate size capacity of file object
|
||||
1 = estimation has been made, bytes was set
|
||||
*/
|
||||
int burn_os_stdio_capacity(char *path, off_t *bytes)
|
||||
{
|
||||
struct stat stbuf;
|
||||
int ret;
|
||||
|
||||
#ifdef Libburn_os_has_statvfS
|
||||
struct statvfs vfsbuf;
|
||||
#endif
|
||||
|
||||
char *testpath = NULL, *cpt;
|
||||
long blocks;
|
||||
off_t add_size = 0;
|
||||
|
||||
BURN_ALLOC_MEM(testpath, char, 4096);
|
||||
|
||||
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)
|
||||
{ret = -1; goto ex;}
|
||||
|
||||
} else if(S_ISBLK(stbuf.st_mode)) {
|
||||
int open_mode = O_RDONLY, fd;
|
||||
|
||||
fd = open(path, open_mode);
|
||||
if (fd == -1)
|
||||
{ret = -2; goto ex;}
|
||||
*bytes = lseek(fd, 0, SEEK_END);
|
||||
close(fd);
|
||||
if (*bytes == -1) {
|
||||
*bytes = 0;
|
||||
{ret = 0; goto ex;}
|
||||
}
|
||||
|
||||
} else if(S_ISREG(stbuf.st_mode)) {
|
||||
add_size = stbuf.st_blocks * (off_t) 512;
|
||||
strcpy(testpath, path);
|
||||
} else
|
||||
{ret = 0; goto ex;}
|
||||
|
||||
if (testpath[0]) {
|
||||
|
||||
#ifdef Libburn_os_has_statvfS
|
||||
|
||||
if (statvfs(testpath, &vfsbuf) == -1)
|
||||
{ret = -2; goto ex;}
|
||||
*bytes = add_size + ((off_t) vfsbuf.f_frsize) *
|
||||
(off_t) vfsbuf.f_bavail;
|
||||
|
||||
#else /* Libburn_os_has_statvfS */
|
||||
|
||||
{ret = 0; goto ex;}
|
||||
|
||||
#endif /* ! Libburn_os_has_stavtfS */
|
||||
|
||||
}
|
||||
ret = 1;
|
||||
ex:;
|
||||
BURN_FREE_MEM(testpath);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* ts A91122 : an interface to open(O_DIRECT) or similar OS tricks. */
|
||||
|
||||
#ifdef Libburn_read_o_direcT
|
||||
|
||||
/* No special O_DIRECT-like precautions are implemented here */
|
||||
|
||||
#endif /* Libburn_read_o_direcT */
|
||||
|
||||
|
||||
int burn_os_open_track_src(char *path, int open_flags, int flag)
|
||||
{
|
||||
int fd;
|
||||
|
||||
fd = open(path, open_flags);
|
||||
return fd;
|
||||
}
|
||||
|
||||
|
||||
void *burn_os_alloc_buffer(size_t amount, int flag)
|
||||
{
|
||||
void *buf = NULL;
|
||||
|
||||
buf = calloc(1, amount);
|
||||
return buf;
|
||||
}
|
||||
|
||||
|
||||
int burn_os_free_buffer(void *buffer, size_t amount, int flag)
|
||||
{
|
||||
if (buffer == NULL)
|
||||
return 0;
|
||||
free(buffer);
|
||||
return 1;
|
||||
}
|
||||
|
62
libburn/sg.c
62
libburn/sg.c
@ -1,13 +1,71 @@
|
||||
|
||||
/* ts A61013 : It would be nice if autotools could do that job */
|
||||
/* sg.c
|
||||
Switcher for operating system dependent transport level modules of libburn.
|
||||
Copyright (C) 2009 - 2010 Thomas Schmitt <scdbackup@gmx.net>,
|
||||
provided under GPLv2+
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#undef HAVE_CONFIG_H
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef Libburn_use_sg_dummY
|
||||
|
||||
#include "sg-dummy.c"
|
||||
|
||||
#else
|
||||
#ifdef Libburn_use_libcdiO
|
||||
|
||||
#include "sg-libcdio.c"
|
||||
|
||||
#else
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#include "sg-freebsd.c"
|
||||
|
||||
#else
|
||||
#ifdef __FreeBSD_kernel__
|
||||
|
||||
#include "sg-freebsd.c"
|
||||
|
||||
#else
|
||||
#ifdef __linux
|
||||
|
||||
#include "sg-linux.c"
|
||||
|
||||
#endif
|
||||
#else
|
||||
#ifdef __sun
|
||||
|
||||
#include "sg-solaris.c"
|
||||
|
||||
#else
|
||||
|
||||
/* The dummy adapter formally fulfills the expectations of libburn towards
|
||||
its SCSI command transport. It will show no drives and perform no SCSI
|
||||
commands.
|
||||
libburn will then be restricted to using its stdio pseudo drives.
|
||||
*/
|
||||
static int intentional_compiler_warning(void)
|
||||
{
|
||||
int INTENTIONAL_COMPILER_WARNING_;
|
||||
int Cannot_recognize_GNU_Linux_nor_FreeBSD_;
|
||||
int Have_to_use_dummy_MMC_transport_adapter_;
|
||||
int This_libburn_will_not_be_able_to_operate_on_real_CD_drives;
|
||||
int Have_to_use_dummy_MMC_transport_adapter;
|
||||
int Cannot_recognize_GNU_Linux_nor_FreeBSD;
|
||||
int INTENTIONAL_COMPILER_WARNING;
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
#include "sg-dummy.c"
|
||||
|
||||
#endif /* ! __sun */
|
||||
#endif /* ! __linux */
|
||||
#endif /* ! __FreeBSD_kernel__ */
|
||||
#endif /* ! __FreeBSD__ */
|
||||
#endif /* ! Libburn_use_libcdiO */
|
||||
#endif /* ! Libburn_use_sg_dummY */
|
||||
|
||||
|
98
libburn/sg.h
98
libburn/sg.h
@ -1,47 +1,22 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
/* Copyright (C) 2009 Thomas Schmitt <scdbackup@gmx.net>, provided under GPLv2+
|
||||
*/
|
||||
|
||||
#ifndef __SG
|
||||
#define __SG
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
/* >>> To hold all state information of BSD device enumeration
|
||||
which are now local in sg_enumerate() . So that sg_give_next_adr()
|
||||
can work in BSD and sg_enumerate() can use it. */
|
||||
struct burn_drive_enumeration_state {
|
||||
#include "os.h"
|
||||
|
||||
#ifdef Scsi_freebsd_old_sg_enumeratE
|
||||
int dummy;
|
||||
#else
|
||||
union ccb ccb;
|
||||
int bufsize, fd;
|
||||
unsigned int i;
|
||||
int skip_device;
|
||||
#endif /* ! Scsi_freebsd_old_sg_enumeratE */
|
||||
|
||||
};
|
||||
typedef struct burn_drive_enumeration_state burn_drive_enumerator_t;
|
||||
/* see os.h for name of particular os-*.h where this is defined */
|
||||
BURN_OS_DEFINE_DRIVE_ENUMERATOR_T
|
||||
|
||||
#else /* __FreeBSD__ */
|
||||
|
||||
/* <<< just for testing the C syntax */
|
||||
struct burn_drive_enumeration_state {
|
||||
int dummy;
|
||||
};
|
||||
typedef struct burn_drive_enumeration_state burn_drive_enumerator_tX;
|
||||
|
||||
typedef int burn_drive_enumerator_t;
|
||||
|
||||
#endif /* ! __FreeBSD__ */
|
||||
|
||||
struct burn_drive;
|
||||
struct command;
|
||||
|
||||
enum response
|
||||
{ RETRY, FAIL };
|
||||
|
||||
/* ts A60925 : ticket 74 */
|
||||
int sg_close_drive_fd(char *fname, int driveno, int *fd, int sorry);
|
||||
|
||||
/* ts A60922 ticket 33 */
|
||||
int sg_give_next_adr(burn_drive_enumerator_t *enm_context,
|
||||
@ -50,19 +25,60 @@ int sg_is_enumerable_adr(char *adr);
|
||||
int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
|
||||
int *target_no, int *lun_no);
|
||||
|
||||
/* ts A60926 : ticket 33 ++ */
|
||||
int sg_open_scsi_siblings(char *fname, int driveno,
|
||||
int sibling_fds[], int *sibling_count,
|
||||
int host_no, int channel_no, int id_no, int lun_no);
|
||||
int sg_release_siblings(int sibling_fds[], int *sibling_count);
|
||||
int sg_close_drive(struct burn_drive *d);
|
||||
|
||||
void sg_enumerate(void);
|
||||
void ata_enumerate(void);
|
||||
int sg_grab(struct burn_drive *);
|
||||
int sg_release(struct burn_drive *);
|
||||
int sg_issue_command(struct burn_drive *, struct command *);
|
||||
enum response scsi_error(struct burn_drive *, unsigned char *, int);
|
||||
|
||||
/* ts A61115 : formerly sg_enumerate();ata_enumerate() */
|
||||
int scsi_enumerate_drives(void);
|
||||
|
||||
int sg_drive_is_open(struct burn_drive * d);
|
||||
|
||||
int burn_os_is_2k_seekrw(char *path, int flag);
|
||||
|
||||
int burn_os_stdio_capacity(char *path, off_t *bytes);
|
||||
|
||||
/* ts A91227 */
|
||||
/** Returns the id string of the SCSI transport adapter and eventually
|
||||
needed operating system facilities.
|
||||
This call is usable even if sg_initialize() was not called yet. In that
|
||||
case a preliminary constant message might be issued if detailed info is
|
||||
not available yet.
|
||||
@param msg returns id string
|
||||
@param flag unused yet, submit 0
|
||||
@return 1 = success, <=0 = failure
|
||||
*/
|
||||
int sg_id_string(char msg[1024], int flag);
|
||||
|
||||
/* ts A91225 */
|
||||
/** Performs global initialization of the SCSI transport adapter and eventually
|
||||
needed operating system facilities. Checks for compatibility supporting
|
||||
software components.
|
||||
@param msg returns ids and/or error messages of eventual helpers
|
||||
@param flag unused yet, submit 0
|
||||
@return 1 = success, <=0 = failure
|
||||
*/
|
||||
int sg_initialize(char msg[1024], int flag);
|
||||
|
||||
/* ts A91227 */
|
||||
/** Performs global finalization of the SCSI transport adapter and eventually
|
||||
needed operating system facilities. Releases globally aquired resources.
|
||||
@param flag unused yet, submit 0
|
||||
@return 1 = success, <=0 = failure
|
||||
*/
|
||||
int sg_shutdown(int flag);
|
||||
|
||||
/* ts A91227 */
|
||||
/** Finalizes BURN_OS_TRANSPORT_DRIVE_ELEMENTS, the components of
|
||||
struct burn_drive which are defined in os-*.h.
|
||||
The eventual initialization of those components was made underneath
|
||||
scsi_enumerate_drives().
|
||||
This will be called when a burn_drive gets disposed.
|
||||
@param d the drive to be finalized
|
||||
@param flag unused yet, submit 0
|
||||
@return 1 = success, <=0 = failure
|
||||
*/
|
||||
int sg_dispose_drive(struct burn_drive *d, int flag);
|
||||
|
||||
|
||||
#endif /* __SG */
|
||||
|
@ -1,5 +1,15 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
#include "libburn.h"
|
||||
@ -18,10 +28,12 @@ void burn_source_free(struct burn_source *src)
|
||||
enum burn_source_status burn_track_set_source(struct burn_track *t,
|
||||
struct burn_source *s)
|
||||
{
|
||||
if (!s->read)
|
||||
return BURN_SOURCE_FAILED;
|
||||
s->refcount++;
|
||||
t->source = s;
|
||||
|
||||
/* ts A61031 */
|
||||
t->open_ended = (s->get_size(s) <= 0);
|
||||
|
||||
return BURN_SOURCE_OK;
|
||||
}
|
||||
|
||||
@ -30,6 +42,36 @@ 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;
|
||||
}
|
||||
|
||||
|
||||
/* ts B00922 */
|
||||
int burn_source_read(struct burn_source *src, unsigned char *buffer, int size)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (src->read != NULL)
|
||||
ret = src->read(src, buffer, size);
|
||||
else
|
||||
ret = src->read_xt(src, buffer, size);
|
||||
return ret;
|
||||
}
|
||||
|
@ -5,4 +5,8 @@
|
||||
|
||||
struct burn_source *burn_source_new(void);
|
||||
|
||||
int burn_source_cancel(struct burn_source *src);
|
||||
|
||||
int burn_source_read(struct burn_source *src, unsigned char *buffer, int size);
|
||||
|
||||
#endif /*__SOURCE*/
|
||||
|
1532
libburn/spc.c
1532
libburn/spc.c
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,11 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __SPC
|
||||
#define __SPC
|
||||
|
||||
@ -20,8 +26,17 @@ void spc_probe_write_modes(struct burn_drive *);
|
||||
void spc_request_sense(struct burn_drive *d, struct buffer *buf);
|
||||
int spc_block_type(enum burn_block_types b);
|
||||
int spc_get_erase_progress(struct burn_drive *d);
|
||||
|
||||
/* ts A70315 : test_unit_ready with result parameters */
|
||||
int spc_test_unit_ready_r(struct burn_drive *d, int *key, int *asc, int *ascq);
|
||||
|
||||
int spc_test_unit_ready(struct burn_drive *d);
|
||||
|
||||
/* ts A70315 */
|
||||
/** Wait until the drive state becomes clear in or until max_sec elapsed */
|
||||
int spc_wait_unit_attention(struct burn_drive *d, int max_sec, char *cmd_text,
|
||||
int flag);
|
||||
|
||||
/* ts A61021 : the spc specific part of sg.c:enumerate_common()
|
||||
*/
|
||||
int spc_setup_drive(struct burn_drive *d);
|
||||
@ -33,5 +48,59 @@ int spc_setup_drive(struct burn_drive *d);
|
||||
int burn_scsi_setup_drive(struct burn_drive *d, int bus_no, int host_no,
|
||||
int channel_no, int target_no, int lun_no, int flag);
|
||||
|
||||
/* ts A61115 moved from sg-*.h */
|
||||
enum response { RETRY, FAIL, GO_ON };
|
||||
enum response scsi_error(struct burn_drive *, unsigned char *, int);
|
||||
|
||||
/* ts A61122 */
|
||||
enum response scsi_error_msg(struct burn_drive *d, unsigned char *sense,
|
||||
int senselen, char msg[161],
|
||||
int *key, int *asc, int *ascq);
|
||||
|
||||
/* ts A61030 */
|
||||
/* @param flag bit0=do report conditions which are considered not an error */
|
||||
int scsi_notify_error(struct burn_drive *, struct command *c,
|
||||
unsigned char *sense, int senselen, int flag);
|
||||
|
||||
/* ts A70519 */
|
||||
int scsi_init_command(struct command *c, unsigned char *opcode, int oplen);
|
||||
|
||||
/* ts A91106 */
|
||||
int scsi_show_cmd_text(struct command *c, void *fp, int flag);
|
||||
|
||||
/* ts A91106 */
|
||||
int scsi_show_cmd_reply(struct command *c, void *fp, int flag);
|
||||
|
||||
/* ts A91218 (former sg_log_cmd ts A70518) */
|
||||
/** Logs command (before execution) */
|
||||
int scsi_log_cmd(struct command *c, void *fp, int flag);
|
||||
|
||||
/* ts A91221 (former sg_log_err ts A91108) */
|
||||
/** Logs outcome of a sg command. */
|
||||
int scsi_log_err(struct command *c, void *fp, unsigned char sense[18],
|
||||
int sense_len, int duration, int flag);
|
||||
|
||||
/* ts B00728 */
|
||||
int spc_decode_sense(unsigned char *sense, int senselen,
|
||||
int *key, int *asc, int *ascq);
|
||||
|
||||
/* ts B00808 */
|
||||
/** Evaluates outcome of a single SCSI command, eventually logs sense data,
|
||||
and issues DEBUG error message in case the command is evaluated as done.
|
||||
@param flag bit1 = do not print duration
|
||||
@return 0 = not yet done , 1 = done , -1 = error
|
||||
*/
|
||||
int scsi_eval_cmd_outcome(struct burn_drive *d, struct command *c, void *fp_in,
|
||||
unsigned char *sense, int sense_len,
|
||||
int duration, time_t start_time, int timeout_ms,
|
||||
int loop_count, int flag);
|
||||
|
||||
/* The waiting time before eventually retrying a failed SCSI command.
|
||||
Before each retry wait Libburn_scsi_retry_incR longer than with
|
||||
the previous one.
|
||||
*/
|
||||
#define Libburn_scsi_retry_usleeP 100000
|
||||
#define Libburn_scsi_retry_incR 100000
|
||||
|
||||
|
||||
#endif /*__SPC*/
|
||||
|
@ -1,4 +1,13 @@
|
||||
|
||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||
Copyright (c) 2006 - 2011 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
/* ts A61008 */
|
||||
/* #include <a ssert.h> */
|
||||
|
||||
@ -9,6 +18,7 @@
|
||||
#include "structure.h"
|
||||
#include "write.h"
|
||||
#include "debug.h"
|
||||
#include "init.h"
|
||||
|
||||
#include "libdax_msgs.h"
|
||||
extern struct libdax_msgs *libdax_messenger;
|
||||
@ -24,7 +34,7 @@ extern struct libdax_msgs *libdax_messenger;
|
||||
return 0;\
|
||||
if (pos == BURN_POS_END)\
|
||||
pos = TO->NEW##s;\
|
||||
if (pos > TO->NEW##s)\
|
||||
if ((int) pos > TO->NEW##s)\
|
||||
return 0;\
|
||||
\
|
||||
tmp = realloc(TO->NEW, sizeof(struct NEW *) * (TO->NEW##s + 1));\
|
||||
@ -40,6 +50,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 +76,8 @@ struct burn_session *burn_session_create(void)
|
||||
{
|
||||
struct burn_session *s;
|
||||
s = calloc(1, sizeof(struct burn_session));
|
||||
if (s == NULL) /* ts A70825 */
|
||||
return NULL;
|
||||
s->refcnt = 1;
|
||||
s->tracks = 0;
|
||||
s->track = NULL;
|
||||
@ -100,10 +114,36 @@ int burn_disc_add_session(struct burn_disc *d, struct burn_session *s,
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* ts A81202: this function was in the API but not implemented.
|
||||
*/
|
||||
int burn_disc_remove_session(struct burn_disc *d, struct burn_session *s)
|
||||
{
|
||||
int i, skip = 0;
|
||||
|
||||
if (d->session == NULL)
|
||||
return 0;
|
||||
for (i = 0; i < d->sessions; i++) {
|
||||
if (s == d->session[i]) {
|
||||
skip++;
|
||||
continue;
|
||||
}
|
||||
d->session[i - skip] = d->session[i];
|
||||
}
|
||||
if (!skip)
|
||||
return 0;
|
||||
burn_session_free(s);
|
||||
d->sessions--;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
struct burn_track *burn_track_create(void)
|
||||
{
|
||||
struct burn_track *t;
|
||||
t = calloc(1, sizeof(struct burn_track));
|
||||
if (t == NULL) /* ts A70825 */
|
||||
return NULL;
|
||||
t->refcnt = 1;
|
||||
t->indices = 0;
|
||||
t->offset = 0;
|
||||
@ -113,8 +153,27 @@ struct burn_track *burn_track_create(void)
|
||||
t->mode = BURN_MODE1;
|
||||
t->isrc.has_isrc = 0;
|
||||
t->pad = 1;
|
||||
|
||||
/* ts A70213 */
|
||||
t->fill_up_media = 0;
|
||||
/* ts A70218 */
|
||||
t->default_size = 0;
|
||||
|
||||
t->entry = NULL;
|
||||
t->source = NULL;
|
||||
t->eos = 0;
|
||||
|
||||
/* ts A61101 */
|
||||
t->sourcecount = 0;
|
||||
t->writecount = 0;
|
||||
t->written_sectors = 0;
|
||||
|
||||
/* ts A61031 */
|
||||
t->open_ended = 0;
|
||||
t->track_data_done = 0;
|
||||
/* ts B10103 */
|
||||
t->end_on_premature_eoi = 0;
|
||||
|
||||
t->postgap = 0;
|
||||
t->pregap1 = 0;
|
||||
t->pregap2 = 0;
|
||||
@ -211,13 +270,14 @@ void burn_track_define_data(struct burn_track *t, int offset, int tail,
|
||||
int burn_sector_length(int tracktype);
|
||||
unsigned char ctladr;
|
||||
int form = -1; /* unchanged form will be considered an error too */
|
||||
char msg[80];
|
||||
|
||||
type_to_form(mode, &ctladr, &form);
|
||||
if (form == -1 || burn_sector_length(mode) <= 0) {
|
||||
char msg[160];
|
||||
|
||||
sprintf(msg, "Attempt to set track mode to unusable value %d",
|
||||
mode);
|
||||
sprintf(msg,
|
||||
"Attempt to set track mode to unusable value 0x%X",
|
||||
(unsigned int) mode);
|
||||
libdax_msgs_submit(libdax_messenger, -1, 0x00020115,
|
||||
LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_PRIO_HIGH,
|
||||
msg, 0, 0);
|
||||
@ -234,13 +294,23 @@ void burn_track_define_data(struct burn_track *t, int offset, int tail,
|
||||
/* ts A61024 */
|
||||
int burn_track_set_byte_swap(struct burn_track *t, int swap_source_bytes)
|
||||
{
|
||||
if(swap_source_bytes!=0 && swap_source_bytes!=1)
|
||||
if (swap_source_bytes != 0 && swap_source_bytes != 1)
|
||||
return 0;
|
||||
t->swap_source_bytes = swap_source_bytes;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* ts A90911 : API */
|
||||
int burn_track_set_cdxa_conv(struct burn_track *t, int value)
|
||||
{
|
||||
if (value < 0 || value > 1)
|
||||
return 0;
|
||||
t->cdxa_conversion = value;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
void burn_track_set_isrc(struct burn_track *t, char *country, char *owner,
|
||||
unsigned char year, unsigned int serial)
|
||||
{
|
||||
@ -306,11 +376,25 @@ void burn_track_clear_isrc(struct burn_track *t)
|
||||
|
||||
int burn_track_get_sectors(struct burn_track *t)
|
||||
{
|
||||
int size;
|
||||
/* ts A70125 : was int */
|
||||
off_t size = 0;
|
||||
int sectors, seclen;
|
||||
|
||||
seclen = burn_sector_length(t->mode);
|
||||
size = t->offset + t->source->get_size(t->source) + t->tail;
|
||||
|
||||
if (t->cdxa_conversion == 1)
|
||||
/* ts A90911 : will read blocks of 2056 bytes and write 2048 */
|
||||
seclen += 8;
|
||||
|
||||
if (t->source != NULL) /* ts A80808 : mending sigsegv */
|
||||
size = t->offset + t->source->get_size(t->source) + t->tail;
|
||||
else if(t->entry != NULL) {
|
||||
/* ts A80808 : all burn_toc_entry of track starts should now
|
||||
have (extensions_valid & 1), even those from CD.
|
||||
*/
|
||||
if (t->entry->extensions_valid & 1)
|
||||
size = ((off_t) t->entry->track_blocks) * (off_t) 2048;
|
||||
}
|
||||
sectors = size / seclen;
|
||||
if (size % seclen)
|
||||
sectors++;
|
||||
@ -318,6 +402,113 @@ int burn_track_get_sectors(struct burn_track *t)
|
||||
return sectors;
|
||||
}
|
||||
|
||||
|
||||
/* ts A70125 */
|
||||
int burn_track_set_sectors(struct burn_track *t, int sectors)
|
||||
{
|
||||
off_t size, seclen;
|
||||
int ret;
|
||||
|
||||
seclen = burn_sector_length(t->mode);
|
||||
size = seclen * (off_t) sectors - (off_t) t->offset - (off_t) t->tail;
|
||||
if (size < 0)
|
||||
return 0;
|
||||
ret = t->source->set_size(t->source, size);
|
||||
t->open_ended = (t->source->get_size(t->source) <= 0);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* ts A70218 , API since A70328 */
|
||||
int burn_track_set_size(struct burn_track *t, off_t size)
|
||||
{
|
||||
if (t->source == NULL)
|
||||
return 0;
|
||||
if (t->source->set_size == NULL)
|
||||
return 0;
|
||||
t->open_ended = (size <= 0);
|
||||
return t->source->set_size(t->source, size);
|
||||
}
|
||||
|
||||
|
||||
/* ts A70213 */
|
||||
int burn_track_set_fillup(struct burn_track *t, int fill_up_media)
|
||||
{
|
||||
t->fill_up_media = fill_up_media;
|
||||
if (fill_up_media)
|
||||
t->open_ended = 0;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* ts A70213 */
|
||||
/**
|
||||
@param flag bit0= force new size even if existing track size is larger
|
||||
*/
|
||||
int burn_track_apply_fillup(struct burn_track *t, off_t max_size, int flag)
|
||||
{
|
||||
int max_sectors, ret = 2;
|
||||
char msg[80];
|
||||
|
||||
if (t->fill_up_media <= 0)
|
||||
return 2;
|
||||
max_sectors = max_size / 2048;
|
||||
if (burn_track_get_sectors(t) < max_sectors || (flag & 1)) {
|
||||
sprintf(msg, "Setting total track size to %ds (payload %ds)\n",
|
||||
max_sectors & 0x7fffffff,
|
||||
(int) ((t->source->get_size(t->source) / 2048)
|
||||
& 0x7fffffff));
|
||||
libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
|
||||
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
|
||||
msg, 0, 0);
|
||||
ret = burn_track_set_sectors(t, max_sectors);
|
||||
t->open_ended = 0;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
/* ts A61031 */
|
||||
int burn_track_is_open_ended(struct burn_track *t)
|
||||
{
|
||||
return !!t->open_ended;
|
||||
}
|
||||
|
||||
|
||||
/* ts A70218 : API */
|
||||
int burn_track_set_default_size(struct burn_track *t, off_t size)
|
||||
{
|
||||
t->default_size = size;
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
||||
/* ts A70218 */
|
||||
off_t burn_track_get_default_size(struct burn_track *t)
|
||||
{
|
||||
return t->default_size;
|
||||
}
|
||||
|
||||
|
||||
/* ts A61101 : API function */
|
||||
int burn_track_get_counters(struct burn_track *t,
|
||||
off_t *read_bytes, off_t *written_bytes)
|
||||
{
|
||||
/*
|
||||
fprintf(stderr, "libburn_experimental: sizeof(off_t)=%d\n",
|
||||
sizeof(off_t));
|
||||
*/
|
||||
*read_bytes = t->sourcecount;
|
||||
*written_bytes = t->writecount;
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* ts A61031 */
|
||||
int burn_track_is_data_done(struct burn_track *t)
|
||||
{
|
||||
return !!t->track_data_done;
|
||||
}
|
||||
|
||||
int burn_track_get_shortage(struct burn_track *t)
|
||||
{
|
||||
int size;
|
||||
@ -339,6 +530,7 @@ int burn_session_get_sectors(struct burn_session *s)
|
||||
return sectors;
|
||||
}
|
||||
|
||||
|
||||
int burn_disc_get_sectors(struct burn_disc *d)
|
||||
{
|
||||
int sectors = 0, i;
|
||||
@ -350,13 +542,19 @@ int burn_disc_get_sectors(struct burn_disc *d)
|
||||
|
||||
void burn_track_get_entry(struct burn_track *t, struct burn_toc_entry *entry)
|
||||
{
|
||||
memcpy(entry, t->entry, sizeof(struct burn_toc_entry));
|
||||
if (t->entry == NULL)
|
||||
memset(entry, 0, sizeof(struct burn_toc_entry));
|
||||
else
|
||||
memcpy(entry, t->entry, sizeof(struct burn_toc_entry));
|
||||
}
|
||||
|
||||
void burn_session_get_leadout_entry(struct burn_session *s,
|
||||
struct burn_toc_entry *entry)
|
||||
{
|
||||
memcpy(entry, s->leadout_entry, sizeof(struct burn_toc_entry));
|
||||
if (s->leadout_entry == NULL)
|
||||
memset(entry, 0, sizeof(struct burn_toc_entry));
|
||||
else
|
||||
memcpy(entry, s->leadout_entry, sizeof(struct burn_toc_entry));
|
||||
}
|
||||
|
||||
struct burn_session **burn_disc_get_sessions(struct burn_disc *d, int *num)
|
||||
@ -380,3 +578,88 @@ int burn_session_get_hidefirst(struct burn_session *session)
|
||||
{
|
||||
return session->hidefirst;
|
||||
}
|
||||
|
||||
|
||||
/* ts A80808 : Enhance CD toc to DVD toc */
|
||||
int burn_disc_cd_toc_extensions(struct burn_disc *d, int flag)
|
||||
{
|
||||
int sidx= 0, tidx= 0, ret;
|
||||
struct burn_toc_entry *entry, *prev_entry= NULL;
|
||||
/* ts A81126 : ticket 146 : There was a SIGSEGV in here */
|
||||
char *msg_data = NULL, *msg;
|
||||
|
||||
BURN_ALLOC_MEM(msg_data, char, 321);
|
||||
strcpy(msg_data,
|
||||
"Damaged CD table-of-content detected and truncated.");
|
||||
strcat(msg_data, " In burn_disc_cd_toc_extensions: ");
|
||||
msg = msg_data + strlen(msg_data);
|
||||
if (d->session == NULL) {
|
||||
strcpy(msg, "d->session == NULL");
|
||||
goto failure;
|
||||
}
|
||||
for (sidx = 0; sidx < d->sessions; sidx++) {
|
||||
if (d->session[sidx] == NULL) {
|
||||
sprintf(msg, "d->session[%d of %d] == NULL",
|
||||
sidx, d->sessions);
|
||||
goto failure;
|
||||
}
|
||||
if (d->session[sidx]->track == NULL) {
|
||||
sprintf(msg, "d->session[%d of %d]->track == NULL",
|
||||
sidx, d->sessions);
|
||||
goto failure;
|
||||
}
|
||||
if (d->session[sidx]->leadout_entry == NULL) {
|
||||
sprintf(msg,
|
||||
" Session %d of %d: Leadout entry missing.",
|
||||
sidx, d->sessions);
|
||||
goto failure;
|
||||
}
|
||||
for (tidx = 0; tidx < d->session[sidx]->tracks + 1; tidx++) {
|
||||
if (tidx < d->session[sidx]->tracks) {
|
||||
if (d->session[sidx]->track[tidx] == NULL) {
|
||||
sprintf(msg,
|
||||
"d->session[%d of %d]->track[%d of %d] == NULL",
|
||||
sidx, d->sessions, tidx, d->session[sidx]->tracks);
|
||||
goto failure;
|
||||
}
|
||||
entry = d->session[sidx]->track[tidx]->entry;
|
||||
if (entry == NULL) {
|
||||
sprintf(msg,
|
||||
"session %d of %d, track %d of %d, entry == NULL",
|
||||
sidx, d->sessions, tidx,
|
||||
d->session[sidx]->tracks);
|
||||
goto failure;
|
||||
}
|
||||
} else
|
||||
entry = d->session[sidx]->leadout_entry;
|
||||
entry->session_msb = 0;
|
||||
entry->point_msb = 0;
|
||||
entry->start_lba = burn_msf_to_lba(entry->pmin,
|
||||
entry->psec, entry->pframe);
|
||||
if (tidx > 0) {
|
||||
prev_entry->track_blocks =
|
||||
entry->start_lba
|
||||
- prev_entry->start_lba;
|
||||
prev_entry->extensions_valid |= 1;
|
||||
}
|
||||
if (tidx == d->session[sidx]->tracks) {
|
||||
entry->session_msb = 0;
|
||||
entry->point_msb = 0;
|
||||
entry->track_blocks = 0;
|
||||
entry->extensions_valid |= 1;
|
||||
}
|
||||
prev_entry = entry;
|
||||
}
|
||||
}
|
||||
{ret = 1; goto ex;}
|
||||
failure:
|
||||
libdax_msgs_submit(libdax_messenger, -1, 0x0002015f,
|
||||
LIBDAX_MSGS_SEV_MISHAP, LIBDAX_MSGS_PRIO_HIGH, msg_data, 0, 0);
|
||||
d->sessions= sidx;
|
||||
ret = 0;
|
||||
ex:;
|
||||
BURN_FREE_MEM(msg_data);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
|
@ -1,3 +1,9 @@
|
||||
|
||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||
Copyright (c) 2006 - 2011 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
#ifndef BURN__STRUCTURE_H
|
||||
#define BURN__STRUCTURE_H
|
||||
|
||||
@ -27,10 +33,37 @@ struct burn_track
|
||||
int tailcount;
|
||||
/** 1 means Pad with zeros, 0 means start reading the next track */
|
||||
int pad;
|
||||
|
||||
/* ts A70213 : wether to expand this track to full available media */
|
||||
int fill_up_media;
|
||||
|
||||
/* ts A70218 : a track size to use if it is mandarory to have some */
|
||||
off_t default_size;
|
||||
|
||||
/** Data source */
|
||||
struct burn_source *source;
|
||||
/** End of Source flag */
|
||||
int eos;
|
||||
|
||||
/* ts A61101 */
|
||||
off_t sourcecount;
|
||||
off_t writecount;
|
||||
off_t written_sectors;
|
||||
|
||||
/* ts A61031 */
|
||||
/** Source is of undefined length */
|
||||
int open_ended;
|
||||
/** End of open ended track flag : offset+payload+tail are delivered */
|
||||
int track_data_done;
|
||||
/* ts B10103 */
|
||||
/** End track writing on premature End-of-input if source is of
|
||||
defined length.
|
||||
0= normal operation in case of eoi
|
||||
1= be ready to end track writing on eoi
|
||||
2= eoi was encountered with previously set value of 1
|
||||
*/
|
||||
int end_on_premature_eoi;
|
||||
|
||||
/** The audio/data mode for the entry. Derived from control and
|
||||
possibly from reading the track's first sector. */
|
||||
int mode;
|
||||
@ -45,6 +78,10 @@ struct burn_track
|
||||
/* ts A61024 */
|
||||
/** Byte swapping on source data stream : 0=none , 1=pairwise */
|
||||
int swap_source_bytes;
|
||||
|
||||
/* ts A90910 : conversions from CD XA prepared input */
|
||||
int cdxa_conversion; /* 0=none, 1=remove -xa1 headers (first 8 bytes)*/
|
||||
|
||||
};
|
||||
|
||||
struct burn_session
|
||||
@ -71,4 +108,27 @@ struct burn_disc
|
||||
|
||||
int burn_track_get_shortage(struct burn_track *t);
|
||||
|
||||
|
||||
/* ts A61031 : might go to libburn.h */
|
||||
int burn_track_is_open_ended(struct burn_track *t);
|
||||
int burn_track_is_data_done(struct burn_track *t);
|
||||
|
||||
/* ts A70125 : sets overall sectors of a track: offset+payload+padding */
|
||||
int burn_track_set_sectors(struct burn_track *t, int sectors);
|
||||
|
||||
/* ts A70218 : sets the payload size alone */
|
||||
int burn_track_set_size(struct burn_track *t, off_t size);
|
||||
|
||||
/* ts A70213 */
|
||||
int burn_track_set_fillup(struct burn_track *t, int fill_up_media);
|
||||
int burn_track_apply_fillup(struct burn_track *t, off_t max_size, int flag);
|
||||
|
||||
/* ts A70218 */
|
||||
off_t burn_track_get_default_size(struct burn_track *t);
|
||||
|
||||
|
||||
/* ts A80808 : Enhance CD toc to DVD toc */
|
||||
int burn_disc_cd_toc_extensions(struct burn_disc *d, int flag);
|
||||
|
||||
|
||||
#endif /* BURN__STRUCTURE_H */
|
||||
|
@ -1,5 +1,15 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||
Copyright (c) 2011 - 2011 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
/* ts A61008 */
|
||||
/* #include <a ssert.h> */
|
||||
|
||||
@ -11,6 +21,7 @@
|
||||
#include "libburn.h"
|
||||
#include "sector.h"
|
||||
#include "options.h"
|
||||
#include "init.h"
|
||||
|
||||
#if 0
|
||||
static void write_clonecd2(volatile struct toc *toc, int f);
|
||||
@ -96,15 +107,14 @@ void toc_find_modes(struct burn_drive *d)
|
||||
{
|
||||
struct burn_read_opts o;
|
||||
int lba;
|
||||
int i, j;
|
||||
struct buffer mem;
|
||||
int i, j, ret;
|
||||
struct buffer *mem = NULL;
|
||||
struct burn_toc_entry *e;
|
||||
|
||||
/* ts A61008 : to be prevented on the higher levels */
|
||||
/* a ssert(d->busy); */
|
||||
BURN_ALLOC_MEM(mem, struct buffer, 1);
|
||||
|
||||
mem.bytes = 0;
|
||||
mem.sectors = 1;
|
||||
mem->bytes = 0;
|
||||
mem->sectors = 1;
|
||||
o.raw = 1;
|
||||
o.c2errors = 0;
|
||||
o.subcodes_audio = 1;
|
||||
@ -128,9 +138,17 @@ void toc_find_modes(struct burn_drive *d)
|
||||
if (e && !(e->control & 4)) {
|
||||
t->mode = BURN_AUDIO;
|
||||
} else {
|
||||
mem.sectors = 1;
|
||||
d->read_sectors(d, lba, mem.sectors, &o, &mem);
|
||||
t->mode = sector_identify(mem.data);
|
||||
|
||||
t->mode = BURN_MODE1;
|
||||
/* ts A70519 : this does not work with GNU/Linux 2.4 USB because one cannot
|
||||
predict the exact dxfer_size without knowing the sector type.
|
||||
mem->sectors = 1;
|
||||
d->read_sectors(d, lba, mem.sectors, &o, mem);
|
||||
t->mode = sector_identify(mem->data);
|
||||
*/
|
||||
}
|
||||
}
|
||||
|
||||
ex:
|
||||
BURN_FREE_MEM(mem);
|
||||
}
|
||||
|
@ -1,5 +1,10 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __TOC_H
|
||||
#define __TOC_H
|
||||
|
||||
|
@ -1,23 +1,25 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef __TRANSPORT
|
||||
#define __TRANSPORT
|
||||
|
||||
#include "libburn.h"
|
||||
#include "os.h"
|
||||
|
||||
#include <pthread.h>
|
||||
/* sg data structures */
|
||||
#include <sys/types.h>
|
||||
|
||||
#ifdef __FreeBSD__
|
||||
|
||||
#define BUFFER_SIZE 65536/2
|
||||
/* see os.h for name of particular os-*.h where this is defined */
|
||||
#define BUFFER_SIZE BURN_OS_TRANSPORT_BUFFER_SIZE
|
||||
|
||||
#else /* __FreeBSD__ */
|
||||
|
||||
#define BUFFER_SIZE 65536
|
||||
|
||||
#endif /* ! __FreeBSD__ */
|
||||
|
||||
enum transfer_direction
|
||||
{ TO_DRIVE, FROM_DRIVE, NO_TRANSFER };
|
||||
@ -40,7 +42,14 @@ struct params
|
||||
|
||||
struct buffer
|
||||
{
|
||||
unsigned char data[BUFFER_SIZE];
|
||||
/* ts A61219:
|
||||
Added 4096 bytes reserve against possible buffer overflows.
|
||||
(Changed in sector.c buffer flush test from >= to > BUFFER_SIZE .
|
||||
This can at most cause a 1 sector overlap. Sometimes an offset
|
||||
of 16 byte is applied to the output data (in some RAW mode). )
|
||||
burn_write_opts.cdxa_conversion can imply an offset of 8 bytes.
|
||||
*/
|
||||
unsigned char data[BUFFER_SIZE + 4096];
|
||||
int sectors;
|
||||
int bytes;
|
||||
};
|
||||
@ -50,6 +59,7 @@ struct command
|
||||
unsigned char opcode[16];
|
||||
int oplen;
|
||||
int dir;
|
||||
int dxfer_len;
|
||||
unsigned char sense[128];
|
||||
int error;
|
||||
int retry;
|
||||
@ -64,6 +74,7 @@ struct burn_scsi_inquiry_data
|
||||
int valid;
|
||||
};
|
||||
|
||||
|
||||
struct scsi_mode_data
|
||||
{
|
||||
int buffer_size;
|
||||
@ -83,6 +94,12 @@ struct scsi_mode_data
|
||||
/* ts A61021 */
|
||||
int min_write_speed;
|
||||
|
||||
/* ts A61225 : Results from ACh GET PERFORMANCE, Type 03h
|
||||
Speed values go into *_*_speed */
|
||||
int min_end_lba;
|
||||
int max_end_lba;
|
||||
struct burn_speed_descriptor *speed_descriptors;
|
||||
|
||||
int cur_read_speed;
|
||||
int cur_write_speed;
|
||||
int retry_page_length;
|
||||
@ -95,11 +112,33 @@ struct scsi_mode_data
|
||||
};
|
||||
|
||||
|
||||
#define LIBBURN_SG_MAX_SIBLINGS 16
|
||||
/* ts A70112 : represents a single Formattable Capacity Descriptor as of
|
||||
mmc5r03c.pdf 6.24.3.3 . There can at most be 32 of them. */
|
||||
struct burn_format_descr {
|
||||
/* format type: e.g 0x00 is "Full", 0x15 is "Quick" */
|
||||
int type;
|
||||
|
||||
/* the size in bytes derived from Number of Blocks */
|
||||
off_t size;
|
||||
|
||||
/* the Type Dependent Parameter (usually the write alignment size) */
|
||||
unsigned int tdp;
|
||||
};
|
||||
|
||||
|
||||
/** Gets initialized in enumerate_common() and burn_drive_register() */
|
||||
struct burn_drive
|
||||
{
|
||||
/* ts A70902:
|
||||
0=null-emulation
|
||||
1=MMC drive ,
|
||||
2=stdio random read-write
|
||||
3=stdio sequential write-only
|
||||
4=stdio random read-only
|
||||
5=stdio random write-only
|
||||
*/
|
||||
int drive_role;
|
||||
|
||||
int bus_no;
|
||||
int host;
|
||||
int id;
|
||||
@ -107,15 +146,13 @@ struct burn_drive
|
||||
int lun;
|
||||
char *devname;
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
struct cam_device* cam;
|
||||
#else
|
||||
int fd;
|
||||
/* ts A70302: mmc5r03c.pdf 5.3.2 Physical Interface Standard */
|
||||
int phys_if_std; /* 1=SCSI, 2=ATAPI, 3,4,6=FireWire, 7=SATA, 8=USB */
|
||||
char phys_if_name[80]; /* MMC-5 5.3.2 table 91 , e.g. "SCSI Family" */
|
||||
|
||||
/* see os.h for name of particular os-*.h where this is defined */
|
||||
BURN_OS_TRANSPORT_DRIVE_ELEMENTS
|
||||
|
||||
/* ts A60926 : trying to lock against growisofs /dev/srN, /dev/scdN */
|
||||
int sibling_count;
|
||||
int sibling_fds[LIBBURN_SG_MAX_SIBLINGS];
|
||||
#endif
|
||||
|
||||
/* ts A60904 : ticket 62, contribution by elmom */
|
||||
/**
|
||||
@ -128,20 +165,177 @@ struct burn_drive
|
||||
|
||||
enum burn_disc_status status;
|
||||
int erasable;
|
||||
|
||||
/* ts A61201 from 46h GET CONFIGURATION */
|
||||
int current_profile;
|
||||
char current_profile_text[80];
|
||||
int current_is_cd_profile;
|
||||
int current_is_supported_profile;
|
||||
/* ts A90603 */
|
||||
int current_is_guessed_profile;
|
||||
/* ts A90815 */
|
||||
unsigned char all_profiles[256];
|
||||
int num_profiles;
|
||||
|
||||
/* ts A70128 : MMC-to-MMC feature info from 46h for DVD-RW.
|
||||
Quite internal. Regard as opaque :)
|
||||
*/
|
||||
/* 1 = incremental recording available, 0 = not available */
|
||||
int current_has_feat21h;
|
||||
|
||||
/* Link Size item number 0 from feature 0021h descriptor */
|
||||
int current_feat21h_link_size;
|
||||
|
||||
/* Flags from feature 0023h for formatting BD mmc5r03c.pdf 5.3.13
|
||||
Byte 4 BD-RE:
|
||||
bit0= Cert format 30h sub-type 10b
|
||||
bit1= QCert format 30h sub-type 11b
|
||||
bit2= Expand format 01h
|
||||
bit3= RENoSA format 31h
|
||||
Byte 8 BD-R:
|
||||
bit0= RRM format 32h sub-type 10b
|
||||
*/
|
||||
int current_feat23h_byte4;
|
||||
int current_feat23h_byte8;
|
||||
|
||||
|
||||
/* Flags from feature 002Fh feature descriptor mmc5r03c.pdf 5.3.25 :
|
||||
bit1= DVD-RW supported
|
||||
bit2= Test Write available
|
||||
bit3= DVD-R DL supported
|
||||
bit6= Buffer Under-run Free recording available (page 05h BUFE)
|
||||
Value -1 indicates that no 002Fh was current in the features list.
|
||||
*/
|
||||
int current_feat2fh_byte4;
|
||||
|
||||
/* ts B10524 : whether the damage bit was set for the future track.
|
||||
bit0= damage bit , bit1= nwa valid bit
|
||||
*/
|
||||
int next_track_damaged;
|
||||
|
||||
/* ts A70114 : whether a DVD-RW media holds an incomplete session
|
||||
(which could need closing after write) */
|
||||
int needs_close_session;
|
||||
/* ts A71003 : whether a random write operation was done and no
|
||||
synchronize chache has happened yet */
|
||||
int needs_sync_cache;
|
||||
|
||||
/* ts A80412 : whether to use WRITE12 with Streaming bit set
|
||||
rather than WRITE10. Speeds up DVD-RAM. Might help
|
||||
with BD-RE */
|
||||
int do_stream_recording;
|
||||
|
||||
/* ts A90227 : the LBA where stream recording shall start.
|
||||
Writing to lower LBA will be done without streaming.
|
||||
*/
|
||||
int stream_recording_start;
|
||||
|
||||
/* ts A61218 from 51h READ DISC INFORMATION */
|
||||
int last_lead_in;
|
||||
int last_lead_out;
|
||||
int num_opc_tables; /* ts A91104: -1= not yet known */
|
||||
int bg_format_status; /* 0=needs format start, 1=needs format restart*/
|
||||
int disc_type; /* 0="CD-DA or CD-ROM", 0x10="CD-I", 0x20="CD-ROM XA" */
|
||||
unsigned int disc_id; /* a "32 bit binary integer" */
|
||||
char disc_bar_code[9];
|
||||
int disc_app_code;
|
||||
int disc_info_valid; /* bit0= disc_type , bit1= disc_id ,
|
||||
bit2= disc_bar_code , bit3= disc_app_code
|
||||
bit4= URU bit is set (= unrestricted use)
|
||||
bit5= Erasable bit was set in reply
|
||||
*/
|
||||
|
||||
/* ts A70108 from 23h READ FORMAT CAPACITY mmc5r03c.pdf 6.24 */
|
||||
int format_descr_type; /* 1=unformatted, 2=formatted, 3=unclear */
|
||||
off_t format_curr_max_size; /* meaning depends on format_descr_type */
|
||||
unsigned int format_curr_blsas; /* dito */
|
||||
int best_format_type;
|
||||
off_t best_format_size;
|
||||
|
||||
/* The complete list of format descriptors as read with 23h */
|
||||
int num_format_descr;
|
||||
struct burn_format_descr format_descriptors[32];
|
||||
|
||||
|
||||
volatile int released;
|
||||
|
||||
/* ts A61106 */
|
||||
int silent_on_scsi_error;
|
||||
|
||||
int stdio_fd;
|
||||
|
||||
int nwa; /* next writeable address */
|
||||
int alba; /* absolute lba */
|
||||
int rlba; /* relative lba in section */
|
||||
int start_lba;
|
||||
int end_lba;
|
||||
|
||||
|
||||
/* ts A70131 : from 51h READ DISC INFORMATION Number of Sessions (-1)*/
|
||||
int complete_sessions;
|
||||
/* ts A90107 */
|
||||
int state_of_last_session;
|
||||
|
||||
/* ts A70129 :
|
||||
from 51h READ DISC INFORMATION Last Track Number in Last Session */
|
||||
int last_track_no;
|
||||
/* ts A70212 : from various sources : free space on media (in bytes)
|
||||
With CD this might change after particular write
|
||||
parameters have been set and nwa has been inquired.
|
||||
(e.g. by d->send_write_parameters() ; d->get_nwa()).
|
||||
*/
|
||||
off_t media_capacity_remaining;
|
||||
/* ts A70215 : if > 0 : first lba on media that is too high for write*/
|
||||
int media_lba_limit;
|
||||
|
||||
/* ts A81210 : Upper limit of readable data size,
|
||||
0x7fffffff = unknown */
|
||||
int media_read_capacity;
|
||||
|
||||
/* ts B10314 : Next Writeable Adress for drive_role == 5 */
|
||||
int role_5_nwa;
|
||||
|
||||
int toc_temp;
|
||||
struct burn_disc *disc; /* disc structure */
|
||||
int block_types[4];
|
||||
struct buffer *buffer;
|
||||
struct burn_progress progress;
|
||||
|
||||
/* To be used by mmc.c, sbc.c, spc.c for SCSI commands where the struct
|
||||
content surely does not have to persist while another command gets
|
||||
composed and executed.
|
||||
(Inherently, sending SCSI commands to the same drive cannot be
|
||||
thread-safe. But there are functions which send SCSI commands
|
||||
and also call other such functions. These shall use own allocated
|
||||
command structs and not this struct here.)
|
||||
*/
|
||||
struct command casual_command;
|
||||
|
||||
/* ts A70711 : keeping an eye on the drive buffer */
|
||||
off_t pessimistic_buffer_free;
|
||||
int pbf_altered;
|
||||
int wait_for_buffer_free;
|
||||
int nominal_write_speed;
|
||||
unsigned int wfb_min_usec;
|
||||
unsigned int wfb_max_usec;
|
||||
unsigned int wfb_timeout_sec;
|
||||
unsigned int wfb_min_percent;
|
||||
unsigned int wfb_max_percent;
|
||||
unsigned int pessimistic_writes;
|
||||
unsigned int waited_writes;
|
||||
unsigned int waited_tries;
|
||||
unsigned int waited_usec;
|
||||
|
||||
volatile int cancel;
|
||||
volatile enum burn_drive_status busy;
|
||||
|
||||
/* ts A70929 */
|
||||
pid_t thread_pid;
|
||||
int thread_pid_valid;
|
||||
/* ts B00225 */
|
||||
pthread_t thread_tid;
|
||||
|
||||
|
||||
/* transport functions */
|
||||
int (*grab) (struct burn_drive *);
|
||||
int (*release) (struct burn_drive *);
|
||||
@ -164,6 +358,12 @@ struct burn_drive
|
||||
void (*unlock) (struct burn_drive *);
|
||||
void (*eject) (struct burn_drive *);
|
||||
void (*load) (struct burn_drive *);
|
||||
int (*start_unit) (struct burn_drive *);
|
||||
|
||||
/* ts A90824 : Calming down noisy drives */
|
||||
int (*stop_unit) (struct burn_drive *);
|
||||
int is_stopped;
|
||||
|
||||
void (*read_disc_info) (struct burn_drive *);
|
||||
void (*read_sectors) (struct burn_drive *,
|
||||
int start,
|
||||
@ -176,9 +376,18 @@ struct burn_drive
|
||||
void (*send_write_parameters) (struct burn_drive *,
|
||||
const struct burn_write_opts *);
|
||||
void (*send_cue_sheet) (struct burn_drive *, struct cue_sheet *);
|
||||
|
||||
/* ts A70205 : Announce size of a DVD-R[W] DAO session. */
|
||||
int (*reserve_track) (struct burn_drive *d, off_t size);
|
||||
|
||||
void (*sync_cache) (struct burn_drive *);
|
||||
int (*get_erase_progress) (struct burn_drive *);
|
||||
int (*get_nwa) (struct burn_drive *);
|
||||
int (*get_nwa) (struct burn_drive *, int trackno, int *lba, int *nwa);
|
||||
|
||||
/* ts A70131 : obtain (possibly fake) TOC number and start lba of
|
||||
first track in last complete session */
|
||||
int (*read_multi_session_c1)(struct burn_drive *d,
|
||||
int *trackno, int *start);
|
||||
|
||||
/* ts A61009 : removed d in favor of o->drive */
|
||||
/* void (*close_disc) (struct burn_drive * d,
|
||||
@ -189,6 +398,10 @@ struct burn_drive
|
||||
void (*close_disc) (struct burn_write_opts * o);
|
||||
void (*close_session) ( struct burn_write_opts * o);
|
||||
|
||||
/* ts A61029 */
|
||||
void (*close_track_session) ( struct burn_drive *d,
|
||||
int session, int track);
|
||||
|
||||
int (*test_unit_ready) (struct burn_drive * d);
|
||||
void (*probe_write_modes) (struct burn_drive * d);
|
||||
struct params params;
|
||||
@ -200,8 +413,25 @@ struct burn_drive
|
||||
/* ts A61023 : get size and free space of drive buffer */
|
||||
int (*read_buffer_capacity) (struct burn_drive *d);
|
||||
|
||||
/* ts A61220 : format media (e.g. DVD+RW) */
|
||||
int (*format_unit) (struct burn_drive *d, off_t size, int flag);
|
||||
|
||||
/* ts A70108 */
|
||||
/* mmc5r03c.pdf 6.24 : get list of available formats */
|
||||
int (*read_format_capacities) (struct burn_drive *d, int top_wanted);
|
||||
|
||||
/* ts A70812 */
|
||||
/* mmc5r03c.pdf 6.15 : read data sectors (start and amount in LBA) */
|
||||
int (*read_10) (struct burn_drive *d, int start, int amount,
|
||||
struct buffer *buf);
|
||||
|
||||
};
|
||||
|
||||
/* end of generic 'drive' data structures */
|
||||
|
||||
/* ts A80422 : centralizing this setting for debugging purposes
|
||||
*/
|
||||
int burn_drive_set_media_capacity_remaining(struct burn_drive *d, off_t value);
|
||||
|
||||
|
||||
#endif /* __TRANSPORT */
|
||||
|
293
libburn/util.c
293
libburn/util.c
@ -1,10 +1,25 @@
|
||||
|
||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#include <string.h>
|
||||
|
||||
/* ts A61008 */
|
||||
/* #include <a ssert.h> */
|
||||
|
||||
#include <stdlib.h>
|
||||
#include "../version.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/* ts A80914 : This is unneeded. Version info comes from libburn.h.
|
||||
#include "v ersion.h"
|
||||
*/
|
||||
|
||||
#include "util.h"
|
||||
#include "libburn.h"
|
||||
|
||||
@ -19,7 +34,7 @@ char *burn_strdup(char *s)
|
||||
return NULL;
|
||||
|
||||
l = strlen(s) + 1;
|
||||
ret = malloc(l);
|
||||
ret = calloc(1, l);
|
||||
memcpy(ret, s, l);
|
||||
|
||||
return ret;
|
||||
@ -37,7 +52,7 @@ char *burn_strndup(char *s, int n)
|
||||
return NULL;
|
||||
|
||||
l = strlen(s);
|
||||
ret = malloc(l < n ? l : n);
|
||||
ret = calloc(1, l < n ? l : n);
|
||||
|
||||
memcpy(ret, s, l < n - 1 ? l : n - 1);
|
||||
ret[n - 1] = '\0';
|
||||
@ -47,7 +62,273 @@ char *burn_strndup(char *s, int n)
|
||||
|
||||
void burn_version(int *major, int *minor, int *micro)
|
||||
{
|
||||
*major = BURN_MAJOR_VERSION;
|
||||
*minor = BURN_MINOR_VERSION;
|
||||
*micro = BURN_MICRO_VERSION;
|
||||
/* ts A80408 : switched from configure.ac versioning to libburn.h versioning */
|
||||
*major = burn_header_version_major;
|
||||
*minor = burn_header_version_minor;
|
||||
*micro = burn_header_version_micro;
|
||||
}
|
||||
|
||||
|
||||
struct cd_mid_record {
|
||||
char *manufacturer;
|
||||
int m_li;
|
||||
int s_li;
|
||||
int f_li;
|
||||
int m_lo;
|
||||
int s_lo;
|
||||
int f_lo;
|
||||
char *other_brands;
|
||||
};
|
||||
typedef struct cd_mid_record cd_mid_record_t;
|
||||
|
||||
|
||||
/* ts A90902 */
|
||||
/** API
|
||||
@param flag Bitfield for control purposes,
|
||||
bit0= append "(aka %s)",other_brands to reply
|
||||
*/
|
||||
char *burn_guess_cd_manufacturer(int m_li, int s_li, int f_li,
|
||||
int m_lo, int s_lo, int f_lo, int flag)
|
||||
{
|
||||
static cd_mid_record_t mid_list[]= {
|
||||
{"SKC", 96, 40, 0, 0, 0, 0, ""},
|
||||
{"Ritek Corp" , 96, 43, 30, 0, 0, 0, ""},
|
||||
{"TDK / Ritek" , 97, 10, 0, 0, 0, 0, "TRAXDATA"},
|
||||
{"TDK Corporation" , 97, 15, 0, 0, 0, 0, ""},
|
||||
{"Ritek Corp" , 97, 15, 10, 0, 0, 0, "7-plus, Aopen, PONY, Power Source, TDK, TRAXDATA, HiCO, PHILIPS, Primdisc, Victor.JVC, OPTI STORAGE, Samsung"},
|
||||
{"Mitsubishi Chemical Corporation" , 97, 15, 20, 0, 0, 0, ""},
|
||||
{"Nan-Ya Plastics Corporation" , 97, 15, 30, 0, 0, 0, "Hatron, MMore, Acer, LITEON"},
|
||||
{"Delphi" , 97, 15, 50, 0, 0, 0, ""},
|
||||
{"Shenzhen SG&SAST" , 97, 16, 20, 0, 0, 0, ""},
|
||||
{"Moser Baer India Limited" , 97, 17, 0, 0, 0, 0, "EMTEC, Intenso, YAKUMO, PLATINUM, Silver Circle"},
|
||||
{"SKY media Manufacturing SA" , 97, 17, 10, 0, 0, 0, ""},
|
||||
{"Wing" , 97, 18, 10, 0, 0, 0, ""},
|
||||
{"DDT" , 97, 18, 20, 0, 0, 0, ""},
|
||||
{"Daxon Technology Inc. / Acer" , 97, 22, 60, 0, 0, 0, "Maxmax, Diamond Data, BenQ, gold, SONY"},
|
||||
{"Taiyo Yuden Company Limited" , 97, 24, 0, 0, 0, 0, "Maxell, FUJIFILM, SONY"},
|
||||
{"Sony Corporation" , 97, 24, 10, 0, 0, 0, "LeadData, Imation"},
|
||||
{"Computer Support Italcard s.r.l" , 97, 24, 20, 0, 0, 0, ""},
|
||||
{"Unitech Japan Inc." , 97, 24, 30, 0, 0, 0, ""},
|
||||
{"MPO, France" , 97, 25, 0, 0, 0, 0, "TDK"},
|
||||
{"Hitachi Maxell Ltd." , 97, 25, 20, 0, 0, 0, ""},
|
||||
{"Infodisc Technology Co,Ltd." , 97, 25, 30, 0, 0, 0, "MEMOREX, SPEEDA, Lead data"},
|
||||
{"Xcitec" , 97, 25, 60, 0, 0, 0, ""},
|
||||
{"Fornet International Pte Ltd" , 97, 26, 0, 0, 0, 0, "COMPUSA, Cdhouse"},
|
||||
{"Postech Corporation" , 97, 26, 10, 0, 0, 0, "Mr.Platinum"},
|
||||
{"SKC Co Ltd." , 97, 26, 20, 0, 0, 0, "Infinite"},
|
||||
{"Fuji Photo Film Co,Ltd." , 97, 26, 40, 0, 0, 0, ""},
|
||||
{"Lead Data Inc." , 97, 26, 50, 0, 0, 0, "SONY, Gigastorage, MIRAGE"},
|
||||
{"CMC Magnetics Corporation" , 97, 26, 60, 0, 0, 0, "Daxon, Verbatim, Memorex, Bi-Winner, PLEXTOR, YAMAHA, Melody, Office DEPOT, Philips, eMARK, imation, HyperMedia, Samsung, Shintaro, Techworks"},
|
||||
{"Ricoh Company Limited" , 97, 27, 0, 0, 0, 0, "Sony, Digital Storage, Csita"},
|
||||
{"Plasmon Data Systems Ltd" , 97, 27, 10, 0, 0, 0, "Ritek, TDK, EMTEC, ALPHAPET, MANIA"},
|
||||
{"Princo Corporation" , 97, 27, 20, 0, 0, 0, ""},
|
||||
{"Pioneer" , 97, 27, 30, 0, 0, 0, ""},
|
||||
{"Eastman Kodak Company" , 97, 27, 40, 0, 0, 0, ""},
|
||||
{"Mitsui Chemicals Inc." , 97, 27, 50, 0, 0, 0, "MAM-A, TDK"},
|
||||
{"Ricoh Company Limited" , 97, 27, 60, 0, 0, 0, "Ritek"},
|
||||
{"Gigastorage Corporation" , 97, 28, 10, 0, 0, 0, "MaxMax, Nan-Ya"},
|
||||
{"Multi Media Masters&Machinary SA" , 97, 28, 20, 0, 0, 0, "King, Mmirex"},
|
||||
{"Ritek Corp" , 97, 31, 0, 0, 0, 0, "TDK"},
|
||||
{"Grand Advance Technology Sdn. Bhd." , 97, 31, 30, 0, 0, 0, ""},
|
||||
{"TDK Corporation" , 97, 32, 00, 0, 0, 0, ""},
|
||||
{"Prodisc Technology Inc." , 97, 32, 10, 0, 0, 0, "Smartbuy, Mitsubishi, Digmaster, LG, Media Market"},
|
||||
{"Mitsubishi Chemical Corporation" , 97, 34, 20, 0, 0, 0, "YAMAHA, Verbatim"},
|
||||
{"Mitsui Chemicals Inc." , 97, 48, 50, 0, 0, 0, ""},
|
||||
{"TDK Corporation" , 97, 49, 0, 0, 0, 0, ""},
|
||||
{"", 0, 0, 0, 0, 0, 0, ""}
|
||||
};
|
||||
|
||||
int i, f_li_0;
|
||||
char buf[1024];
|
||||
char *result = NULL;
|
||||
|
||||
if (m_li == 0 && s_li == 2 && f_li == 0) {
|
||||
result = strdup("(no manufacturer code)");
|
||||
return result;
|
||||
}
|
||||
f_li_0 = f_li - (f_li % 10);
|
||||
for (i = 0; mid_list[i].manufacturer[0]; i++) {
|
||||
if (m_li == mid_list[i].m_li &&
|
||||
s_li == mid_list[i].s_li &&
|
||||
(f_li_0 == mid_list[i].f_li || f_li == mid_list[i].f_li))
|
||||
break;
|
||||
}
|
||||
if (mid_list[i].manufacturer[0] == 0) {
|
||||
sprintf(buf, "Unknown CD manufacturer. Please report code '%2.2dm%2.2ds%2.2df/%2.2dm%2.2ds%2.2df', the human readable brand, size, and speed to scdbackup@gmx.net.", m_li, s_li, f_li, m_lo, s_lo, f_lo);
|
||||
result = strdup(buf);
|
||||
return result;
|
||||
}
|
||||
|
||||
/* Compose, allocate and copy result */
|
||||
if ((flag & 1) && mid_list[i].other_brands[0]) {
|
||||
sprintf(buf, "%s (aka %s)",
|
||||
mid_list[i].manufacturer, mid_list[i].other_brands);
|
||||
result = strdup(buf);
|
||||
} else
|
||||
result = strdup(mid_list[i].manufacturer);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* ts A90904 */
|
||||
struct dvd_mid_record {
|
||||
char *mc1;
|
||||
char *mc2;
|
||||
int mc1_sig_len;
|
||||
char *manufacturer;
|
||||
};
|
||||
typedef struct dvd_mid_record dvd_mid_record_t;
|
||||
|
||||
/* ts A90904 */
|
||||
char *burn_guess_manufacturer(int prf,
|
||||
char *media_code1, char *media_code2, int flag)
|
||||
{
|
||||
int i, l = 0, m_li, s_li, f_li, m_lo, s_lo, f_lo;
|
||||
char buf[1024];
|
||||
char *result = NULL, *cpt;
|
||||
|
||||
/* Important Note: media_code1 and media_code2 are supposed to be
|
||||
encoded by burn_util_make_printable_word().
|
||||
Especially: ' ' -> '_' , {"_%/" unprintables -> %XY)
|
||||
*/
|
||||
static dvd_mid_record_t mid_list[]= {
|
||||
{"AML", "", 8, "UML"},
|
||||
{"BeAll", "", 5, "BeAll Developers, Inc."},
|
||||
{"CMC", "", 3, "CMC Magnetics Corporation"},
|
||||
{"DAXON", "", 5, "Daxon Technology Inc. / Acer"},
|
||||
{"Daxon", "", 5, "Daxon Technology Inc. / Acer"},
|
||||
{"FUJI", "", 4, "Fujifilm Holdings Corporation"},
|
||||
{"INFODISC", "", 8, "New Star Digital Co., Ltd."},
|
||||
{"INFOME", "", 6, "InfoMedia Inc."},
|
||||
{"ISMMBD", "", 6, "Info Source Multi Media Ltd."},
|
||||
{"JVC", "", 3, "JVC Limited"},
|
||||
{"KIC01RG", "", 7, "AMC"},
|
||||
{"LD", "", 8, "Lead Data Inc."},
|
||||
{"LGE", "", 3, "LG Electronics"},
|
||||
{"MAM", "", 8, "Mitsui Advanced Media, Inc. Europe"},
|
||||
{"MAXELL", "", 6, "Hitachi Maxell Ltd."},
|
||||
{"MBI", "", 3, "Moser Baer India Limited"},
|
||||
{"MCC", "", 8, "Mitsubishi Chemical Corporation"},
|
||||
{"MCI", "", 8, "Mitsui Chemicals Inc."},
|
||||
{"MEI", "", 3, "Panasonic Corporation"},
|
||||
{"MKM", "", 3, "Mitsubishi Kagaku Media Co."},
|
||||
{"MMC", "", 8, "Mitsubishi Kagaku Media Co."},
|
||||
{"MXL", "", 8, "Hitachi Maxell Ltd."},
|
||||
{"NANYA", "", 5, "Nan-Ya Plastics Corporation"},
|
||||
{"NSD", "", 8, "NESA International Inc."},
|
||||
{"OPTODISC", "", 8, "Optodisc Technology Corporation"},
|
||||
{"OTCBDR", "", 8, "Optodisc Technology Corporation"},
|
||||
{"PHILIP", "", 8, "Moser Baer India Limited"},
|
||||
{"PHILIPS", "", 8, "Philips"},
|
||||
{"PRINCO", "", 6, "Princo Corporation"},
|
||||
{"PRODISC", "", 7, "Prodisc Technology Inc."},
|
||||
{"Prodisc", "", 7, "Prodisc Technology Inc."},
|
||||
{"PVC", "", 3, "Pioneer"},
|
||||
{"RICOHJPN", "", 8, "Ricoh Company Limited"},
|
||||
{"RITEK", "", 5, "Ritek Corp"},
|
||||
{"SONY", "", 4, "Sony Corporation"},
|
||||
{"TDK", "", 3, "TDK Corporation"},
|
||||
{"TT", "", 8, "TDK Corporation"},
|
||||
{"TY", "", 8, "Taiyo Yuden Company Limited"},
|
||||
{"TYG", "", 3, "Taiyo Yuden Company Limited"},
|
||||
{"UTJR001", "", 7, "Unifino Inc."},
|
||||
{"VERBAT", "", 5, "Mitsubishi Kagaku Media Co."},
|
||||
{"YUDEN", "", 5, "Taiyo Yuden Company Limited"},
|
||||
{"", "", 0, ""}
|
||||
};
|
||||
|
||||
if (media_code2 != NULL &&
|
||||
(prf == -1 || prf == 0x09 || prf == 0x0A)) {
|
||||
if (strlen(media_code2) == 9 && media_code1[0] == '9' &&
|
||||
media_code1[2] == 'm' && media_code1[5] == 's' &&
|
||||
media_code1[8] == 'f' &&
|
||||
strchr(media_code1, '%') == NULL) {
|
||||
sscanf(media_code1, "%dm%ds%df", &m_li, &s_li, &f_li);
|
||||
sscanf(media_code2, "%dm%ds%df", &m_lo, &s_lo, &f_lo);
|
||||
if (m_li >= 96 && m_li <= 97 && m_lo > 0) {
|
||||
result = burn_guess_cd_manufacturer(
|
||||
m_li, s_li, f_li, m_lo, s_lo, f_lo, 0);
|
||||
return result;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* DVD-R do not keep manufacturer id apart from media id.
|
||||
Some manufacturers use a blank as separator which would now be '_'.
|
||||
*/
|
||||
cpt = strchr(media_code1, '_');
|
||||
if (cpt != NULL && (prf == -1 || prf == 0x11 || prf == 0x13 ||
|
||||
prf == 0x14 || prf == 0x15))
|
||||
l = cpt - media_code1;
|
||||
|
||||
for (i = 0; mid_list[i].mc1[0]; i++) {
|
||||
if (strncmp(mid_list[i].mc1, media_code1,
|
||||
mid_list[i].mc1_sig_len) == 0)
|
||||
break;
|
||||
if (l > 0)
|
||||
if (strncmp(mid_list[i].mc1, media_code1, l) == 0)
|
||||
break;
|
||||
}
|
||||
if (mid_list[i].mc1[0] == 0) {
|
||||
sprintf(buf, "Unknown DVD/BD manufacturer. Please report code '%s/%s', the human readable brand, size, and speed to scdbackup@gmx.net.",
|
||||
media_code1, media_code2);
|
||||
result = strdup(buf);
|
||||
return result;
|
||||
}
|
||||
result = strdup(mid_list[i].manufacturer);
|
||||
return result;
|
||||
}
|
||||
|
||||
|
||||
/* ts A90905 */
|
||||
/* Make *text a single printable word */
|
||||
/* IMPORTANT: text must be freeable memory !
|
||||
@param flag bit0=escape '/' too
|
||||
bit1=(overrides bit0) do not escape " _/"
|
||||
*/
|
||||
int burn_util_make_printable_word(char **text, int flag)
|
||||
{
|
||||
int i, esc_add = 0, ret;
|
||||
char *wpt, *rpt, *new_text = NULL;
|
||||
|
||||
if (flag & 2)
|
||||
flag &= ~1;
|
||||
|
||||
for (i = 0; (*text)[i]; i++) {
|
||||
rpt = (*text) + i;
|
||||
if (*rpt < 32 || *rpt > 126 || *rpt == 96 ||
|
||||
((*rpt == '_' || *rpt == '%') && (!(flag & 2))) ||
|
||||
(*rpt == '/' && (flag & 1)))
|
||||
esc_add += 2;
|
||||
}
|
||||
if (esc_add) {
|
||||
new_text = calloc(strlen(*text) + esc_add + 1, 1);
|
||||
if (new_text == NULL) {
|
||||
ret = -1;
|
||||
goto ex;
|
||||
}
|
||||
wpt = new_text;
|
||||
for (i = 0; (*text)[i]; i++) {
|
||||
rpt = (*text) + i;
|
||||
if (*rpt < 32 || *rpt > 126 || *rpt == 96 ||
|
||||
((*rpt == '_' || *rpt == '%') && (!(flag & 2))) ||
|
||||
(*rpt == '/' && (flag & 1))) {
|
||||
sprintf(wpt, "%%%2.2X",
|
||||
(unsigned int) *((unsigned char *) rpt));
|
||||
wpt+= 3;
|
||||
} else
|
||||
*(wpt++) = *rpt;
|
||||
}
|
||||
*wpt = 0;
|
||||
free(*text);
|
||||
*text = new_text;
|
||||
}
|
||||
if (!(flag & 2))
|
||||
for (i = 0; (*text)[i]; i++)
|
||||
if ((*text)[i] == ' ')
|
||||
(*text)[i] = '_';
|
||||
ret = 1;
|
||||
ex:
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -5,4 +5,7 @@ char *burn_strdup(char *s);
|
||||
|
||||
char *burn_strndup(char *s, int n);
|
||||
|
||||
/* ts A90905 */
|
||||
int burn_util_make_printable_word(char **text, int flag);
|
||||
|
||||
#endif
|
||||
|
2401
libburn/write.c
2401
libburn/write.c
File diff suppressed because it is too large
Load Diff
@ -1,5 +1,11 @@
|
||||
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
|
||||
|
||||
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
|
||||
Copyright (c) 2006 - 2010 Thomas Schmitt <scdbackup@gmx.net>
|
||||
Provided under GPL version 2 or later.
|
||||
*/
|
||||
|
||||
|
||||
#ifndef BURN__WRITE_H
|
||||
#define BURN__WRITE_H
|
||||
|
||||
@ -9,12 +15,14 @@ struct burn_write_opts;
|
||||
struct burn_disc;
|
||||
|
||||
struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o,
|
||||
struct burn_session *session);
|
||||
struct burn_session *session,
|
||||
int nwa);
|
||||
int burn_sector_length(int trackmode);
|
||||
int burn_subcode_length(int trackmode);
|
||||
|
||||
/* ts A61009 */
|
||||
int burn_disc_write_is_ok(struct burn_write_opts *o, struct burn_disc *disc);
|
||||
int burn_disc_write_is_ok(struct burn_write_opts *o, struct burn_disc *disc,
|
||||
int flag);
|
||||
|
||||
void burn_disc_write_sync(struct burn_write_opts *o, struct burn_disc *disc);
|
||||
int burn_write_leadin(struct burn_write_opts *o,
|
||||
@ -24,6 +32,23 @@ int burn_write_leadout(struct burn_write_opts *o,
|
||||
int burn_write_session(struct burn_write_opts *o, struct burn_session *s);
|
||||
int burn_write_track(struct burn_write_opts *o, struct burn_session *s,
|
||||
int tnum);
|
||||
int burn_write_flush(struct burn_write_opts *o);
|
||||
int burn_write_flush(struct burn_write_opts *o, struct burn_track *track);
|
||||
|
||||
/* ts A61030 : necessary for TAO */
|
||||
int burn_write_close_track(struct burn_write_opts *o, struct burn_session *s,
|
||||
int tnum);
|
||||
int burn_write_close_session(struct burn_write_opts *o);
|
||||
|
||||
|
||||
|
||||
/* mmc5r03c.pdf 6.3.3.3.3: DVD-R DL: Close Function 010b: Close Session
|
||||
"When the recording mode is Incremental Recording,
|
||||
the disc is single session."
|
||||
Enable this macro to get away from growisofs which uses Close Session
|
||||
but also states "// DVD-R DL Seq has no notion of multi-session".
|
||||
|
||||
#define Libburn_dvd_r_dl_multi_no_close_sessioN 1
|
||||
|
||||
*/
|
||||
|
||||
#endif /* BURN__WRITE_H */
|
||||
|
1503
libcevap/cgen.c
Normal file
1503
libcevap/cgen.c
Normal file
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user