Compare commits

...

55 Commits

Author SHA1 Message Date
Thomas Schmitt 6fb158b56d Bug fix: Possible wrong result on Linux when translating /dev/sr address to /dev/sg 2024-04-27 18:28:10 +02:00
Thomas Schmitt 51f43127ac Comitted file which was forgotten with commit f0d9795 2024-03-09 18:59:18 +01:00
Thomas Schmitt f84d038121 Removed remaining 31/32-bit bottlenecks from stdio writing 2024-03-03 21:14:17 +01:00
Thomas Schmitt e5a8d91e4d New API call burn_get_read_capacity_v2() 2024-03-03 16:24:13 +01:00
Thomas Schmitt f0d9795cd1 New API calls burn_disc_get_sectors_v2(), burn_session_get_sectors_v2(), burn_track_get_sectors_v2() 2024-03-03 11:52:15 +01:00
Thomas Schmitt 29bfd7e5e7 New API call burn_disc_track_lba_nwa_v2() 2024-03-02 14:12:22 +01:00
Thomas Schmitt d48bbb4b66 New struct burn_progress_v2 and API call burn_drive_get_status_v2() 2024-03-01 19:51:34 +01:00
Thomas Schmitt 17a020e9fc Augmented struct burn_toc_entry by new off_t block addresses and counters 2024-02-27 20:48:11 +01:00
Thomas Schmitt 069b4edecd Removed use of undefined data by a rarely occuring error message 2024-02-26 16:06:56 +01:00
Thomas Schmitt 84e8efeb0a Changed a byte size variable from int to off_t. Currently only used with CD DAO and thus not really necessary. 2024-02-26 15:58:36 +01:00
Thomas Schmitt ddebbf1b60 Bug fix: burn_offst_source_new() parameter "size" rolled over at 2 exp 31 2024-02-26 15:57:18 +01:00
Thomas Schmitt ca29b77091 Checking length of pseudo-drive address to prevent possible overflow 2023-09-12 15:21:17 +02:00
Thomas Schmitt 046f581baa Changed gpg key server recommendation to keyserver.ubuntu.com. Corrected repo instructions from SVN to git. 2023-06-20 19:56:33 +02:00
Thomas Schmitt c8ceb73b5f Updated change log 2023-06-07 20:40:00 +02:00
Thomas Schmitt f4a09e9536 Made number transition to 1.5.7 2023-06-07 20:36:56 +02:00
Thomas Schmitt 4628231cec Updated change log 2023-06-07 15:54:15 +02:00
Thomas Schmitt f795db5d61 Last minute correction in cdrskin web page 2023-06-07 15:51:14 +02:00
Thomas Schmitt 9acb8ad6da Updated cdrskin tarball generator 2023-06-07 15:33:00 +02:00
Thomas Schmitt 1172ef74c6 Made number transition to 1.5.6 2023-06-07 15:23:54 +02:00
Thomas Schmitt a904ae995a Enlarged maximum allowed tsize= value to 4 TiB - 2 KiB (just in case) 2022-12-10 11:18:05 +01:00
Thomas Schmitt 1954514210 Updated copyright dates of cdrskin 2022-04-05 16:04:43 +02:00
Thomas Schmitt 629a4fa44d Let cdrskin take options -VV and -VVV as -V 2022-04-05 15:59:50 +02:00
Thomas Schmitt 879cb991df Updated change log 2021-11-25 19:11:37 +01:00
Thomas Schmitt d4d63213ab Improved man page of cdrskin about -force after enabling overburning in libburn 2021-11-24 12:47:16 +01:00
Thomas Schmitt 7765fbd1ab Enabled overburning with burn_write_opts_set_force(,1) 2021-11-24 12:45:07 +01:00
Thomas Schmitt da44c706ea New cdrskin option --bdr_obs_exempt 2021-09-12 10:46:28 +02:00
Thomas Schmitt 31591b8196 New API call burn_write_opts_set_bdr_obs_exempt() 2021-09-12 10:41:59 +02:00
Thomas Schmitt 27e15689e5 Let mmc_read_cd() for CD-DA set command.dxfer_len 2021-09-02 20:13:23 +02:00
Thomas Schmitt 0a1bbb1696 Added doc/waveformat.txt to libburn tarball 2021-09-02 20:11:02 +02:00
Thomas Schmitt c76145f5e1 Corrected man page about the default of extract_basename= 2021-09-02 20:09:42 +02:00
Thomas Schmitt 8d270b1fda Removed unneeded configure.ac macro AC_C_BIGENDIAN 2021-09-02 20:07:44 +02:00
Thomas Schmitt 892df643c9 Made optional the use of libcam and thus SCSI passthrough on GNU/FreeBSD systems 2021-03-12 09:28:36 +01:00
Thomas Schmitt 31e8f5cf0e Unified size of large or unlimited pseudo drives to 4 TiB - 32 KiB 2021-02-28 13:20:09 +01:00
Thomas Schmitt 2a977cfc4b Improved error message if a track is larger than 4 TiB - 32 KiB 2021-02-28 13:17:27 +01:00
Thomas Schmitt be039ff191 Updated change log 2021-01-30 16:48:07 +01:00
Thomas Schmitt f1d5c670c5 Made number transition to 1.5.5 2021-01-30 16:46:15 +01:00
Thomas Schmitt d3bd97c05e Updated change log 2021-01-30 16:41:02 +01:00
Thomas Schmitt d146886763 Corrected SONAME parameters to produce libburn.so.4.107.0 2021-01-30 12:51:39 +01:00
Thomas Schmitt d95d5a2484 Updated cdrskin tarball generator 2021-01-30 10:55:10 +01:00
Thomas Schmitt 2a58d5ae5c Made number transition to 1.5.4 2021-01-30 10:52:56 +01:00
Thomas Schmitt 3468a2ad38 Tolerating all sense replies of form 6,28,* 2020-09-30 20:53:53 +02:00
Thomas Schmitt 6b2ae7d141 For now using CDROM_SIMUL_CHANGE only if -DLibburn_use_linux_ioctl_simul_changE 2020-09-20 22:46:55 +02:00
Thomas Schmitt ab6b1039a4 Changed experimental ioctl from CDROM_REVALIDATE to CDROM_SIMUL_CHANGE 2020-09-20 10:45:15 +02:00
Thomas Schmitt 8b9a8cfb4b New API call burn_nominal_slowdown() 2020-08-26 16:04:06 +02:00
Thomas Schmitt 0e1f5dc3da New API call burn_drive_set_speed_exact() 2020-08-24 15:28:15 +02:00
Thomas Schmitt 8d934ee7b8 Testing use of experimental ioctl CDROM_REVALIDATE after media state changes 2020-08-22 15:22:11 +02:00
Thomas Schmitt e09acf3b8a Corrected a typo in man cdrskin found by lintian 2020-07-11 11:47:46 +02:00
Thomas Schmitt 799175019b Bug fix: Early SCSI commands from sg-linux.c were not logged 2020-04-15 20:52:05 +02:00
Thomas Schmitt b57c05c874 Incremented .so numbering to libburn.so.4.106.0 2019-11-26 18:07:40 +01:00
Thomas Schmitt d4593f49ae Updated README about 1.5.2.pl01 2019-11-25 20:36:31 +01:00
Thomas Schmitt 91f7d4d34a Bug fix: cdrskin multi-track burning was slow and stalled after track 1. Regression introduced in version 1.5.0 by commit 84fad99, 2018.02.05 2019-11-25 10:13:29 +01:00
Thomas Schmitt ba9b69b1df Fixed spelling errors found by fossies.org with codespell 2019-10-28 16:58:20 +01:00
Thomas Schmitt 1c235e807e Corrected alphabetical sort rank of --list_features in man cdrskin 2019-10-27 19:37:24 +01:00
Thomas Schmitt 95ad059aba Updated change log 2019-10-27 15:27:45 +01:00
Thomas Schmitt 0a37e8cbe5 Made number transition to 1.5.3 2019-10-27 15:26:21 +01:00
47 changed files with 1695 additions and 526 deletions

View File

@ -1,3 +1,28 @@
git clone git@dev.lovelyhq.com:libburnia/libburn.git
(to become libburn-1.5.8 or higher)
===============================================================================
- no novelties yet -
libburn-1.5.6.tar.gz Wed Jun 07 2023
===============================================================================
* Bug fix: Overburning with cdrskin option -force ended by a libburn error
* New API call burn_write_opts_set_bdr_obs_exempt()
* New cdrskin option --bdr_obs_exempt
* Officially enabled overburning with burn_write_opts_set_force(,1)
libburn-1.5.4.tar.gz Sat Jan 30 2021
===============================================================================
* Bug fix: Early SCSI commands from sg-linux.c were not logged
* New API call burn_drive_set_speed_exact()
* New API call burn_nominal_slowdown()
libburn-1.5.2.pl01.tar.gz Mon Nov 25 2019
===============================================================================
* Bug fix: cdrskin multi-track burning was slow and stalled after track 1.
Regression introduced in version 1.5.0 by commit 84fad99, 2018.02.05
O_DIRECT is now disabled for track sources.
libburn-1.5.2.tar.gz Sat Oct 26 2019 libburn-1.5.2.tar.gz Sat Oct 26 2019
=============================================================================== ===============================================================================
* Bug fix: No lock was obtained for setting up a fifo object * Bug fix: No lock was obtained for setting up a fifo object

View File

@ -114,9 +114,9 @@ test_poll_CPPFLAGS = -Ilibburn
test_poll_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS) test_poll_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
test_poll_SOURCES = test/poll.c test_poll_SOURCES = test/poll.c
## cdrskin construction site - ts A60816 - B91026 ## cdrskin construction site - ts A60816 - C30607
cdrskin_cdrskin_CPPFLAGS = -Ilibburn cdrskin_cdrskin_CPPFLAGS = -Ilibburn
cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_1_5_2 cdrskin_cdrskin_CFLAGS = -DCdrskin_libburn_1_5_7
# cdrskin_cdrskin_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS) # cdrskin_cdrskin_LDADD = $(libburn_libburn_la_OBJECTS) $(LIBBURN_EXTRALIBS)
# ts A80123, change proposed by Simon Huggins to cause dynamic libburn linking # ts A80123, change proposed by Simon Huggins to cause dynamic libburn linking
@ -201,6 +201,7 @@ EXTRA_DIST = \
doc/cookbook.txt \ doc/cookbook.txt \
doc/mediainfo.txt \ doc/mediainfo.txt \
doc/cdtext.txt \ doc/cdtext.txt \
doc/waveformat.txt \
README \ README \
AUTHORS \ AUTHORS \
CONTRIBUTORS \ CONTRIBUTORS \

62
README
View File

@ -6,12 +6,12 @@ This all is under GPL.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
libburnia-project.org libburnia-project.org
By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net> By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
Copyright (C) 2006-2019 Mario Danic, Thomas Schmitt Copyright (C) 2006-2023 Mario Danic, Thomas Schmitt
Still containing parts of Libburn. By Derek Foreman <derek@signalmarketing.com> Still containing parts of Libburn. By Derek Foreman <derek@signalmarketing.com>
and Ben Jansens <xor@orodu.net> and Ben Jansens <xor@orodu.net>
Copyright (C) 2002-2006 Derek Foreman and Ben Jansens Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
http://files.libburnia-project.org/releases/libburn-1.5.2.tar.gz http://files.libburnia-project.org/releases/libburn-1.5.6.tar.gz
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@ -19,10 +19,10 @@ Copyright (C) 2002-2006 Derek Foreman and Ben Jansens
From tarball From tarball
Obtain libburn-1.5.2.tar.gz, take it to a directory of your choice and do: Obtain libburn-1.5.6.tar.gz, take it to a directory of your choice and do:
tar xzf libburn-1.5.2.tar.gz tar xzf libburn-1.5.6.tar.gz
cd libburn-1.5.2 cd libburn-1.5.6
./configure --prefix=/usr ./configure --prefix=/usr
make make
@ -41,21 +41,21 @@ You may have to keep your hald away from the drive. See for example
http://www.freebsd.org/gnome/docs/halfaq.html http://www.freebsd.org/gnome/docs/halfaq.html
From SVN From git
Our build system is based on autotools. For preparing the build of a SVN Our build system is based on autotools. For preparing the build of a git
snapshot you will need autotools of at least version 1.7. snapshot you will need autotools of at least version 1.7.
Do in a directory of your choice: Do in a directory of your choice:
svn co http://svn.libburnia-project.org/libburn/trunk libburn-svn git clone https://dev.lovelyhq.com/libburnia/libburn.git libburn-git
cd libburn-svn cd libburn-git
./bootstrap ./bootstrap
./configure --prefix=/usr ./configure --prefix=/usr
make make
make install make install
Warning: The trunk might contain experimental features which might not Warning: The master branch might contain experimental features which might
persist until next release. not persist until next release.
Special ./configure options Special ./configure options
@ -113,12 +113,11 @@ closing it immediately, waiting, and only then opening it for real:
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
An important part of the project, libisofs, is hosted in a bzr repository at The other parts of the the libburnia project are hosted as neighbors of
launchpad.net : libburn:
bzr branch lp:libisofs
Another part the project, libisoburn, is hosted in the libburnia SVN, too: git clone https://dev.lovelyhq.com/libburnia/libisofs.git
svn co http://svn.libburnia-project.org/libisoburn/trunk libisoburn git clone https://dev.lovelyhq.com/libburnia/libisoburn.git
See README files there. See README files there.
@ -791,6 +790,37 @@ Project history as far as known to me:
partitions and the ISO partition. partitions and the ISO partition.
All three libraries got some rarely triggered bugs fixed. All three libraries got some rarely triggered bugs fixed.
- Mon Nov 25 2019 patch release 1.5.2.pl01
cdrskin did not properly burn multiple tracks. Track 1 was slow and burning
stalled before track 2. Regression introduced by 1.5.0.
- Sat Jan 30 2021 , 07 Feb 2021 release 1.5.4
libburn offers new opportunities to influence drive speed.
libisofs got a bug fixed which under medium rare circumstances spoiled
zisofs production. libisofs switched to usage of libjte-2.0.0. Further it
can now write and read zisofs2 format, which enables compression of files
>= 4 GiB. When reading Joliet file trees, the names get stripped of their
version numbers by default. After loading metadata, libisofs can now tell
which directory tree was loaded and whether Rock Ridge is used.
libisoburn and xorriso make use of these new features.
xorriso can put out the data stream of -check_media to standard output. It
can restore files with many zero bytes as sparse files and it is able to
extract recognized boot images into data files on hard disk.
A new script xorriso-dd-target helps to put an ISO image onto an USB stick
without endangering valuable hard disk content.
Several rarely triggered bugs were fixed.
- Wed Jun 07 2023 release 1.5.6
libburn can overburn CD media, i.e. write more data than the drive announced
as medium capacity.
libisofs can assess many of the features which were in effect when a
given ISO 9660 filesystem was created. A safety limit was introduced not
to exceed the limit of Linux which is imposed on the number of SUSP CE
entries which is good for about 60 KiB of AAIP data. Some rarely occuring
bugs were fixed in libisofs.
libisoburn and xorriso expose the new library features to the user and
got some minor improvements. Many minor bugs were fixed.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
This program is free software; you can redistribute it and/or modify This program is free software; you can redistribute it and/or modify

View File

@ -16,6 +16,7 @@ AC_DEFUN([TARGET_SHIZZLE],
AC_MSG_CHECKING([target operating system]) AC_MSG_CHECKING([target operating system])
libburn_check_libcam=
LIBBURNIA_LDCONFIG_CMD="echo 'No ldconfig run performed. If needed, configure manually for:'" LIBBURNIA_LDCONFIG_CMD="echo 'No ldconfig run performed. If needed, configure manually for:'"
case $target in case $target in
@ -32,6 +33,7 @@ AC_DEFUN([TARGET_SHIZZLE],
*-kfreebsd*-gnu*) *-kfreebsd*-gnu*)
ARCH=freebsd ARCH=freebsd
LIBBURN_ARCH_LIBS=-lcam LIBBURN_ARCH_LIBS=-lcam
libburn_check_libcam=yes
;; ;;
*-solaris*) *-solaris*)
ARCH=solaris ARCH=solaris
@ -43,8 +45,12 @@ AC_DEFUN([TARGET_SHIZZLE],
# AC_ERROR([You are attempting to compile for an unsupported platform]) # AC_ERROR([You are attempting to compile for an unsupported platform])
;; ;;
esac esac
AC_MSG_RESULT([$ARCH]) AC_MSG_RESULT([$ARCH])
if test x"$libburn_check_libcam" = xyes
then
LIBBURNIA_CHECK_LIBCAM
fi
]) ])
@ -120,6 +126,7 @@ dnl It tests whether the OS dependent libraries are available.
dnl With libisoburn they are needed only for the case that indirect linking dnl With libisoburn they are needed only for the case that indirect linking
dnl does not work. So it is worth a try to omit them. dnl does not work. So it is worth a try to omit them.
dnl $1 = "mandatory" or "optional" define the action if test linking fails. dnl $1 = "mandatory" or "optional" define the action if test linking fails.
dnl "silent" is like "optional" but without message.
AC_DEFUN([LIBBURNIA_CHECK_ARCH_LIBS], AC_DEFUN([LIBBURNIA_CHECK_ARCH_LIBS],
[ [
libburnia_save_LIBS="$LIBS" libburnia_save_LIBS="$LIBS"
@ -140,11 +147,19 @@ AC_DEFUN([LIBBURNIA_CHECK_ARCH_LIBS],
echo >&2 echo >&2
(exit 1); exit 1; (exit 1); exit 1;
else else
echo "disabled linking with $LIBBURN_ARCH_LIBS (because not found)" if test x"$1" = xoptional
then
echo "disabled linking with $LIBBURN_ARCH_LIBS (because not found)"
fi
LIBBURN_ARCH_LIBS="" LIBBURN_ARCH_LIBS=""
fi fi
else else
echo "enabled linking with $LIBBURN_ARCH_LIBS" if test x"$1" = xsilent
then
dummy=dummy
else
echo "enabled linking with $LIBBURN_ARCH_LIBS"
fi
fi fi
fi fi
]) ])
@ -155,18 +170,72 @@ dnl
AC_DEFUN([LIBBURNIA_CHECK_LINUX_SCSI], AC_DEFUN([LIBBURNIA_CHECK_LINUX_SCSI],
[ [
dnl Check whether it is a Linux without scsi/scsi.h dnl Check whether it is a Linux without scsi/scsi.h
AH_TEMPLATE([Libburn_use_sg_dummY], libburn_scsi_disabled=
[Define to compile without OS specific SCSI features]) if test x"$ARCH" = xlinux
AC_MSG_CHECKING([for missing scsi/scsi.h on Linux]) then
AC_TRY_COMPILE([ AH_TEMPLATE([Libburn_use_sg_dummY],
[Define to compile without OS specific SCSI features])
AC_MSG_CHECKING([for missing scsi/scsi.h on Linux])
AC_TRY_COMPILE([
#ifdef __linux #ifdef __linux
#include <scsi/scsi.h> #include <scsi/scsi.h>
#endif #endif
], ],
[;], [;],
[AC_MSG_RESULT([no])], [AC_MSG_RESULT([no])],
[AC_DEFINE([Libburn_use_sg_dummY], [yes]) [AC_DEFINE([Libburn_use_sg_dummY], [yes])
AC_MSG_RESULT([yes])] libburn_scsi_disabled=yes
) AC_MSG_RESULT([yes])]
)
fi
if test x"$libburn_scsi_disabled" = xyes
then
echo "disabled operation of optical drives via SCSI"
fi
])
dnl LIBBURNIA_CHECK_LIBCAM is by Thomas Schmitt, libburnia project
dnl
AC_DEFUN([LIBBURNIA_CHECK_LIBCAM],
[
dnl Check whether libcam is requested for FreeBSD kernel but missing
libburn_scsi_disabled=
if test x"$LIBBURN_ARCH_LIBS" = x"-lcam"
then
AH_TEMPLATE([Libburn_use_sg_dummY],
[Define to compile without OS specific SCSI features])
AC_MSG_CHECKING([for missing libcam for SCSI on FreeBSD kernel])
dnl If libcam is not available, LIBBURN_ARCH_LIBS will be made empty
LIBBURNIA_CHECK_ARCH_LIBS(silent)
if test x"$LIBBURN_ARCH_LIBS" = x
then
AC_DEFINE([Libburn_use_sg_dummY], [yes])
libburn_scsi_disabled=yes
AC_MSG_RESULT([yes])
else
AC_MSG_RESULT([no])
fi
fi
if test x"$LIBBURN_ARCH_LIBS" = x"-lcam"
then
AC_MSG_CHECKING([for missing libcam headers])
AC_TRY_COMPILE([
#include <stdio.h>
#include <camlib.h>
#include <cam/scsi/scsi_message.h>
#include <cam/scsi/scsi_pass.h>
],
[;],
[AC_MSG_RESULT([no])],
[AC_DEFINE([Libburn_use_sg_dummY], [yes])
libburn_scsi_disabled=yes
AC_MSG_RESULT([yes])]
)
fi
if test x"$libburn_scsi_disabled" = xyes
then
echo "disabled operation of optical drives via SCSI"
fi
]) ])

View File

@ -4,9 +4,9 @@
cdrskin. By Thomas Schmitt <scdbackup@gmx.net> cdrskin. By Thomas Schmitt <scdbackup@gmx.net>
Integrated sub project of libburnia-project.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_eng.html
http://scdbackup.sourceforge.net/cdrskin-1.5.2.tar.gz http://scdbackup.sourceforge.net/cdrskin-1.5.7.tar.gz
Copyright (C) 2006-2019 Thomas Schmitt, provided under GPL version 2 or later. Copyright (C) 2006-2023 Thomas Schmitt, provided under GPL version 2 or later.
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@ -26,10 +26,10 @@ By using this software you agree to the disclaimer at the end of this text
Compilation, First Glimpse, Installation Compilation, First Glimpse, Installation
Obtain cdrskin-1.5.2.tar.gz, take it to a directory of your choice and do: Obtain cdrskin-1.5.7.tar.gz, take it to a directory of your choice and do:
tar xzf cdrskin-1.5.2.tar.gz tar xzf cdrskin-1.5.7.tar.gz
cd cdrskin-1.5.2 cd cdrskin-1.5.7
Within that directory execute: Within that directory execute:
@ -563,7 +563,7 @@ are the cause. Any mistake of the burn program is supposed to be caught
by the drive's firmware and to lead to mere misburns. by the drive's firmware and to lead to mere misburns.
The worst mishaps which hit the author imposed the need to reboot the The worst mishaps which hit the author imposed the need to reboot the
system because of drives gnawing endlessly on ill media. Permanent hardware 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 ... damage did not occur in 13 years of development. But one never knows ...
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
@ -591,7 +591,7 @@ contributions in a due way.
Based on and sub project of: Based on and sub project of:
libburnia-project.org libburnia-project.org
By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net> By Mario Danic <mario.danic@gmail.com> and Thomas Schmitt <scdbackup@gmx.net>
Copyright (C) 2006-2019 Mario Danic, Thomas Schmitt Copyright (C) 2006-2023 Mario Danic, Thomas Schmitt
libburnia-project.org is inspired by and in other components still containing libburnia-project.org is inspired by and in other components still containing
parts of parts of

View File

@ -38,7 +38,7 @@ original="./libburn_svn_release.tgz"
# My changes are in $changes , mainly in $changes/cdrskin # My changes are in $changes , mainly in $changes/cdrskin
changes="./libburn-release" changes="./libburn-release"
skin_release="1.5.2" skin_release="1.5.6"
patch_level="" patch_level=""
# patch_level=".pl00" # patch_level=".pl00"
skin_rev="$skin_release""$patch_level" skin_rev="$skin_release""$patch_level"

View File

@ -38,7 +38,7 @@ original="./libburn_svn.tgz"
# My changes are in $changes , mainly in $changes/cdrskin # My changes are in $changes , mainly in $changes/cdrskin
changes="./libburn-develop" changes="./libburn-develop"
skin_release="1.5.3" skin_release="1.5.7"
patch_level="" patch_level=""
skin_rev="$skin_release""$patch_level" skin_rev="$skin_release""$patch_level"

View File

@ -28,7 +28,20 @@
#ifndef Cdrfifo_standalonE #ifndef Cdrfifo_standalonE
/* for burn_os_alloc_buffer() */ /* for burn_os_alloc_buffer() */
#include "../libburn/libburn.h" #include "../libburn/libburn.h"
#define Libburn_has_open_trac_srC 1
/* ts B91124:
DISABLED, because this spoils multi-track burning by slowing down first
track and stalling before the second track begins. Obviously a problem
with chained input and waiting for full O_DRIECT suitable read chunks.
DO NOT ENABLE before the wait code in this source file is fixed.
That long, ./configure option --enable-track-src-odirect must not
get into effect in libburn. NO -DLibburn_read_o_direcT either.
For extra safety, O_DIRECT has been banned in libburn/sg-linux.c too.
# def ine Libburn_has_open_trac_srC 1
*/
#endif #endif
#include "cdrfifo.h" #include "cdrfifo.h"

View File

@ -2,7 +2,7 @@
.\" First parameter, NAME, should be all caps .\" First parameter, NAME, should be all caps
.\" Second parameter, SECTION, should be 1-8, maybe w/ subsection .\" Second parameter, SECTION, should be 1-8, maybe w/ subsection
.\" other parameters are allowed: see man(7), man(1) .\" other parameters are allowed: see man(7), man(1)
.TH CDRSKIN 1 "Version 1.5.2, Oct 26, 2019" .TH CDRSKIN 1 "Version 1.5.7, Jun 07, 2023"
.\" Please adjust this date whenever revising the manpage. .\" Please adjust this date whenever revising the manpage.
.\" .\"
.\" Some roff macros, for reference: .\" Some roff macros, for reference:
@ -573,9 +573,14 @@ Eject the disc after work is done.
.TP .TP
.BI \-force .BI \-force
Assume that the user knows better in situations when cdrskin or libburn are Assume that the user knows better in situations when cdrskin or libburn are
insecure about drive or media state. This includes the attempt to blank refusing because of concerns about drive or media state.
.br
.B Caution:
Use option -force only when in urgent need.
.br
This option enables the attempt to blank
media which are classified as unknown or unsuitable, and the attempt to use media which are classified as unknown or unsuitable, and the attempt to use
write modes which libburn believes they are not supported by the drive. write modes of which libburn believes they are not supported by the drive.
.br .br
Another application is to enforce blanking or re-formatting of media Another application is to enforce blanking or re-formatting of media
which appear to be in the desired blank or format state already. which appear to be in the desired blank or format state already.
@ -584,10 +589,22 @@ This option enables a burn run with option -dummy even if libburn believes
that drive and media will not simulate the write mode but will write for real. that drive and media will not simulate the write mode but will write for real.
.br .br
It enables a burn run where cdrskin expects to exceed the available media It enables a burn run where cdrskin expects to exceed the available media
capacity. capacity. This is known as "overburn" and might succeed on CD media with
write type SAO.
.B Too much overburning
might be
.B harmful to the medium
and might
.B make the drive unusable
(hopefully only until it gets powered off and on). The man page of cdrecord
mentions 88 seconds = 6600 blocks as halfways safe amount over the official
medium capacity. The assessment of track sizes by libburn will be wrong if
the written size reaches or exceeds 90 minutes = 405000 sectors. The overall
medium size assessment by the Linux kernel is supposed to yield roughly the
written size, but you should test this yourself with every overburnt medium.
.br .br
.B Caution: First consider to use a medium with more capacity rather than trying to
Use this only when in urgent need. overburn a CD.
.TP .TP
.BI \-format .BI \-format
Same as blank=format_overwrite_full -force but restricted to DVD+RW. Same as blank=format_overwrite_full -force but restricted to DVD+RW.
@ -1087,11 +1104,11 @@ This directory has to already exist, but none of the track files may exist.
This option will rather fail than overwrite an existing file. This option will rather fail than overwrite an existing file.
.br .br
By default all tracks of the CD are extracted to files with names By default all tracks of the CD are extracted to files with names
trackNN.wav, where NN is the track number from 01 to at most 99. NN.wav, where NN is the track number from 01 to at most 99.
.TP .TP
.BI extract_basename= name .BI extract_basename= name
Set a filename which shall be used by extract_audio_to= instead of the default Set a filename prefix which shall be used by extract_audio_to= instead of the
name "track". empty default name prefix.
.TP .TP
.BI --extract_dap .BI --extract_dap
Enable Digital Audio Play flaw obscuring mechanisms Enable Digital Audio Play flaw obscuring mechanisms
@ -1451,7 +1468,7 @@ full.
.br .br
If a write attempt is delayed, the program will wait for a number of If a write attempt is delayed, the program will wait for a number of
microseconds which is given by parameter "min_usec" before inquiring the buffer microseconds which is given by parameter "min_usec" before inquiring the buffer
again. iIf more retries occur, this waiting time between inquiries increases again. If more retries occur, this waiting time between inquiries increases
up to the value of parameter "max_usec". up to the value of parameter "max_usec".
.br .br
If the delay lasts longer than the number of seconds given by parameter If the delay lasts longer than the number of seconds given by parameter
@ -1471,46 +1488,6 @@ better buffer fills while still avoiding the problem:
Alphabetical list of options which are only intended for very special Alphabetical list of options which are only intended for very special
situations and not for normal use: situations and not for normal use:
.TP .TP
.BI \--list_features
List the SCSI/MMC features which were obtained from the drive when it was
last acquired or re-assessed. Although this is better readable than the
raw reply to SCSI command GET CONFIGURATION, the MMC specification text
is still needed for interpreting it.
.br
The list consists of line groups of the form
.br
Code +/- : Name : Version,P/N
.br
Raw feature data bytes as hex numbers
.br
Parsed info as Name=Value pairs
.br
The headline is the only one which has no blank at its start.
Code is given as 16 bit hex number.
.br
"+" marks a currently offered feature. "-" marks those which may be offered
under different circumstances.
.br
Name is the feature name as listed in MMC specs.
.br
"P" marks persistent features. "N" marks non-persistent features.
.br
The Raw data can occupy more than one line. No "=" occurs in such lines.
If no raw data are present, one line with some blanks is listed instead.
.br
The Parsed info shows some extracted field values with names which resemble
the names used in the MMC description of the particular feature. Parsed info
lines contain at least one Name=Value pair. More than one line is possible.
If no parsed info is produced, one line with some blanks is listed instead.
.br
Example:
.br
0107 - : Real Time Streaming : 4,N
.br
1f 00 00 00
.br
RBCB=1 , SCS=1 , MP2A=1 , WSPD=1 , SW=1
.TP
.BI \--abort_handler .BI \--abort_handler
Establish default signal handling not to leave a drive in busy state Establish default signal handling not to leave a drive in busy state
but rather to shut it down and to wait until it has ended the final operations. but rather to shut it down and to wait until it has ended the final operations.
@ -1621,6 +1598,46 @@ Try to ignore any signals rather than to abort the program. This is not a
very good idea. You might end up waiting a very long time for cdrskin very good idea. You might end up waiting a very long time for cdrskin
to finish. to finish.
.TP .TP
.BI \--list_features
List the SCSI/MMC features which were obtained from the drive when it was
last acquired or re-assessed. Although this is better readable than the
raw reply to SCSI command GET CONFIGURATION, the MMC specification text
is still needed for interpreting it.
.br
The list consists of line groups of the form
.br
Code +/- : Name : Version,P/N
.br
Raw feature data bytes as hex numbers
.br
Parsed info as Name=Value pairs
.br
The headline is the only one which has no blank at its start.
Code is given as 16 bit hex number.
.br
"+" marks a currently offered feature. "-" marks those which may be offered
under different circumstances.
.br
Name is the feature name as listed in MMC specs.
.br
"P" marks persistent features. "N" marks non-persistent features.
.br
The Raw data can occupy more than one line. No "=" occurs in such lines.
If no raw data are present, one line with some blanks is listed instead.
.br
The Parsed info shows some extracted field values with names which resemble
the names used in the MMC description of the particular feature. Parsed info
lines contain at least one Name=Value pair. More than one line is possible.
If no parsed info is produced, one line with some blanks is listed instead.
.br
Example:
.br
0107 - : Real Time Streaming : 4,N
.br
1f 00 00 00
.br
RBCB=1 , SCS=1 , MP2A=1 , WSPD=1 , SW=1
.TP
.BI \--no_abort_handler .BI \--no_abort_handler
On signals exit even if the drive is in busy state. This is not a very good On signals exit even if the drive is in busy state. This is not a very good
idea. You might end up with a stuck drive that refuses to hand out the media. idea. You might end up with a stuck drive that refuses to hand out the media.
@ -1640,16 +1657,27 @@ addresses which are not listed with cdrskin --devices but nevertheless point
to a usable drive. (Like /dev/sg0 using the same SCSI address as /dev/sr0.) to a usable drive. (Like /dev/sg0 using the same SCSI address as /dev/sr0.)
.TP .TP
.BI \--obs_pad .BI \--obs_pad
Pad the data of last write operation of a DVD-R[W] DAO session or Pad the data of the last write operation of a DVD-R[W] DAO session, or BD-R
stdio: pseudo-drive up to the full size of an output chunk. session, or stdio: pseudo-drive session up to the full size of an output chunk.
This padding has to be applied automatically to the other DVD and BD media This padding has to be applied automatically to the other DVD and BD media
types, where it causes e.g. ISO images to have trailing unclaimed blocks. types, where it causes e.g. ISO images to have trailing unclaimed blocks.
Whether it is applied automatically to BD-R depends on option
--bdr_obs_exempt.
.br .br
Use this option if there is the suspicion that DAO sessions abort with Use this option if there is the suspicion that DVD-R[W] DAO or BD-R sessions
your kernel and/or DVD drive, if their size is not a multiple of 16 blocks. abort with your kernel and/or DVD drive, if their size is not a multiple of
16 blocks.
.br .br
This option may also get enabled at compile time of libburn. This option may also get enabled at compile time of libburn.
.TP .TP
.BI \--bdr_obs_exempt
Exempt BD-R media from automatic unconditional transaction end padding,
provided that this padding is not requested by --obs_pad and that
no stream_recording is requested.
.br
This is a new feature introduced with version 1.5.6. It might become default
in later versions.
.TP
.BI \--old_pseudo_scsi_adr .BI \--old_pseudo_scsi_adr
Linux specific: Linux specific:
Use and report literal Bus,Target,Lun addresses rather than real SCSI and Use and report literal Bus,Target,Lun addresses rather than real SCSI and

View File

@ -1,6 +1,6 @@
/* /*
cdrskin.c , Copyright 2006-2019 Thomas Schmitt <scdbackup@gmx.net> cdrskin.c , Copyright 2006-2023 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later. Provided under GPL version 2 or later.
A cdrecord compatible command line interface for libburn. A cdrecord compatible command line interface for libburn.
@ -87,7 +87,7 @@ or
/** The official program version */ /** The official program version */
#ifndef Cdrskin_prog_versioN #ifndef Cdrskin_prog_versioN
#define Cdrskin_prog_versioN "1.5.2" #define Cdrskin_prog_versioN "1.5.7"
#endif #endif
/** The official libburn interface revision to use. /** The official libburn interface revision to use.
@ -100,7 +100,7 @@ or
#define Cdrskin_libburn_minoR 5 #define Cdrskin_libburn_minoR 5
#endif #endif
#ifndef Cdrskin_libburn_micrO #ifndef Cdrskin_libburn_micrO
#define Cdrskin_libburn_micrO 2 #define Cdrskin_libburn_micrO 6
#endif #endif
@ -120,34 +120,34 @@ or
#undef Cdrskin_libburn_versioN #undef Cdrskin_libburn_versioN
#endif #endif
#ifdef Cdrskin_libburn_1_5_2 #ifdef Cdrskin_libburn_1_5_6
#define Cdrskin_libburn_versioN "1.5.2" #define Cdrskin_libburn_versioN "1.5.6"
#endif #endif
#ifdef Cdrskin_libburn_1_5_3 #ifdef Cdrskin_libburn_1_5_7
#define Cdrskin_libburn_versioN "1.5.3" #define Cdrskin_libburn_versioN "1.5.7"
#endif #endif
#ifndef Cdrskin_libburn_versioN #ifndef Cdrskin_libburn_versioN
#define Cdrskin_libburn_1_5_2 #define Cdrskin_libburn_1_5_6
#define Cdrskin_libburn_versioN "1.5.2" #define Cdrskin_libburn_versioN "1.5.6"
#endif #endif
#ifdef Cdrskin_libburn_1_5_2 #ifdef Cdrskin_libburn_1_5_6
#undef Cdrskin_libburn_majoR #undef Cdrskin_libburn_majoR
#undef Cdrskin_libburn_minoR #undef Cdrskin_libburn_minoR
#undef Cdrskin_libburn_micrO #undef Cdrskin_libburn_micrO
#define Cdrskin_libburn_majoR 1 #define Cdrskin_libburn_majoR 1
#define Cdrskin_libburn_minoR 5 #define Cdrskin_libburn_minoR 5
#define Cdrskin_libburn_micrO 2 #define Cdrskin_libburn_micrO 6
#endif #endif
#ifdef Cdrskin_libburn_1_5_3 #ifdef Cdrskin_libburn_1_5_7
#undef Cdrskin_libburn_majoR #undef Cdrskin_libburn_majoR
#undef Cdrskin_libburn_minoR #undef Cdrskin_libburn_minoR
#undef Cdrskin_libburn_micrO #undef Cdrskin_libburn_micrO
#define Cdrskin_libburn_majoR 1 #define Cdrskin_libburn_majoR 1
#define Cdrskin_libburn_minoR 5 #define Cdrskin_libburn_minoR 5
#define Cdrskin_libburn_micrO 3 #define Cdrskin_libburn_micrO 7
#endif #endif
@ -2914,6 +2914,8 @@ set_dev:;
printf( printf(
" --no_rc as first argument: do not read startup files\n"); " --no_rc as first argument: do not read startup files\n");
printf(" --obs_pad pad DVD DAO to full 16 or 32 blocks\n"); printf(" --obs_pad pad DVD DAO to full 16 or 32 blocks\n");
printf(
" --bdr_obs_exempt possibly exempt BD-R from padding to full 64k\n");
printf(" --old_pseudo_scsi_adr use and report literal Bus,Target,Lun\n"); printf(" --old_pseudo_scsi_adr use and report literal Bus,Target,Lun\n");
printf(" rather than real SCSI and pseudo ATA.\n"); printf(" rather than real SCSI and pseudo ATA.\n");
printf( printf(
@ -3152,7 +3154,8 @@ see_cdrskin_eng_html:;
} else if(strncmp(argpt ,"textfile_to_v07t=", 17) == 0) { } else if(strncmp(argpt ,"textfile_to_v07t=", 17) == 0) {
o->do_not_scan= 1; o->do_not_scan= 1;
} else if(strcmp(argv[i],"-V")==0 || strcmp(argpt, "-Verbose") == 0) { } else if(strcmp(argv[i],"-V")==0 || strcmp(argpt, "-Verbose") == 0 ||
strcmp(argv[i],"-VV")==0 || strcmp(argpt, "-VVV") == 0) {
burn_set_scsi_logging(2 | 4); /* log SCSI to stderr */ burn_set_scsi_logging(2 | 4); /* log SCSI to stderr */
} else if(strcmp(argv[i],"-v")==0 || strcmp(argpt, "-verbose") == 0) { } else if(strcmp(argv[i],"-v")==0 || strcmp(argpt, "-verbose") == 0) {
@ -3173,7 +3176,7 @@ set_severities:;
int major, minor, micro; int major, minor, micro;
printf( printf(
"Cdrecord 2.01a27 Emulation. Copyright (C) 2006-2018, see libburnia-project.org\n"); "Cdrecord 2.01a27 Emulation. Copyright (C) 2006-2023, see libburnia-project.org\n");
if(o->fallback_program[0]) { if(o->fallback_program[0]) {
char *hargv[2]; char *hargv[2];
@ -3340,7 +3343,8 @@ ex:;
*/ */
#define Cdrskin_tracksize_maX 1024.0*1024.0*1024.0*1024.0 /* 4 TiB - 32 KiB : The libburn API works with int rather than uint32_t */
#define Cdrskin_tracksize_maX 4398046478336.0
/* Some constants obtained by hearsay and experiments */ /* Some constants obtained by hearsay and experiments */
@ -3391,6 +3395,9 @@ struct CdrskiN {
int stream_recording_is_set; /* see burn_write_opts_set_stream_recording() */ int stream_recording_is_set; /* see burn_write_opts_set_stream_recording() */
int dvd_obs; /* DVD write chunk size: 0, 32k or 64k */ int dvd_obs; /* DVD write chunk size: 0, 32k or 64k */
int obs_pad; /* Whether to force obs end padding */ int obs_pad; /* Whether to force obs end padding */
int bdr_obs_exempt; /* Whether to possibly exempt BD-R from automatic
obs_pad
*/
int stdio_sync; /* stdio fsync interval: -1, 0, >=32 */ int stdio_sync; /* stdio fsync interval: -1, 0, >=32 */
int single_track; int single_track;
int prodvd_cli_compatible; int prodvd_cli_compatible;
@ -3665,6 +3672,7 @@ int Cdrskin_new(struct CdrskiN **skin, struct CdrpreskiN *preskin, int flag)
o->stream_recording_is_set= 0; o->stream_recording_is_set= 0;
o->dvd_obs= 0; o->dvd_obs= 0;
o->obs_pad= 0; o->obs_pad= 0;
o->bdr_obs_exempt= 0;
o->stdio_sync= 0; o->stdio_sync= 0;
o->single_track= 0; o->single_track= 0;
o->prodvd_cli_compatible= 0; o->prodvd_cli_compatible= 0;
@ -4453,6 +4461,13 @@ int Cdrskin_driveno_to_btldev(struct CdrskiN *skin, int driveno,
loc= adr; loc= adr;
ret= burn_drive_get_drive_role(skin->drives[driveno].drive); ret= burn_drive_get_drive_role(skin->drives[driveno].drive);
if(ret!=1) { if(ret!=1) {
if(strlen(adr) > Cdrskin_adrleN - 7) {
fprintf(stderr,
"cdrskin : FAILURE : File path too long for \"stdio:\" prefix: %s\n",
adr);
sprintf(btldev, "stdio:"); /* Address of the null drive */
return(-1);
}
sprintf(btldev,"stdio:%s",adr); sprintf(btldev,"stdio:%s",adr);
{ret= 2; goto adr_translation;} {ret= 2; goto adr_translation;}
} }
@ -7697,6 +7712,7 @@ burn_failed:;
#endif #endif
burn_write_opts_set_dvd_obs(o, skin->dvd_obs); burn_write_opts_set_dvd_obs(o, skin->dvd_obs);
burn_write_opts_set_obs_pad(o, skin->obs_pad); burn_write_opts_set_obs_pad(o, skin->obs_pad);
burn_write_opts_set_bdr_obs_exempt(o, skin->bdr_obs_exempt);
burn_write_opts_set_stdio_fsync(o, skin->stdio_sync); burn_write_opts_set_stdio_fsync(o, skin->stdio_sync);
if(skin->dummy_mode) { if(skin->dummy_mode) {
@ -9169,6 +9185,9 @@ msifile_equals:;
} else if(strcmp(argv[i],"--obs_pad")==0) { } else if(strcmp(argv[i],"--obs_pad")==0) {
skin->obs_pad= 1; skin->obs_pad= 1;
} else if(strcmp(argv[i],"--bdr_obs_exempt")==0) {
skin->bdr_obs_exempt= 1;
} else if(strcmp(argv[i],"--old_pseudo_scsi_adr")==0) { } else if(strcmp(argv[i],"--old_pseudo_scsi_adr")==0) {
/* is handled in Cdrpreskin_setup() */; /* is handled in Cdrpreskin_setup() */;
@ -9396,7 +9415,8 @@ track_too_large:;
return(0); return(0);
} }
} else if(strcmp(argv[i],"-V")==0 || strcmp(argpt, "-Verbose")==0) { } else if(strcmp(argv[i],"-V") == 0 || strcmp(argpt, "-Verbose") == 0 ||
strcmp(argv[i],"-VV") == 0 || strcmp(argpt, "-VVV") == 0) {
/* is handled in Cdrpreskin_setup() */; /* is handled in Cdrpreskin_setup() */;
} else if(strcmp(argv[i],"-v")==0 || strcmp(argpt,"-verbose")==0) { } else if(strcmp(argv[i],"-v")==0 || strcmp(argpt,"-verbose")==0) {
/* is handled in Cdrpreskin_setup() */; /* is handled in Cdrpreskin_setup() */;

View File

@ -67,7 +67,7 @@ with drives connected via SCSI, PATA (aka IDE, ATA), USB, or SATA.
GPL software included:<BR> GPL software included:<BR>
</H2> </H2>
<DL> <DL>
<DT>libburn-1.5.2</DT> <DT>libburn-1.5.6</DT>
<DD>(founded by Derek Foreman and Ben Jansens, <DD>(founded by Derek Foreman and Ben Jansens,
developed and maintained since August 2006 by developed and maintained since August 2006 by
Thomas Schmitt from team of libburnia-project.org) Thomas Schmitt from team of libburnia-project.org)
@ -202,15 +202,15 @@ Standalone ISO 9660 multi-session CD/DVD/BD tool
<P> <P>
<DL> <DL>
<DT>Download as source code (see README):</DT> <DT>Download as source code (see README):</DT>
<DD><A HREF="cdrskin-1.5.2.tar.gz">cdrskin-1.5.2.tar.gz</A> <DD><A HREF="cdrskin-1.5.6.tar.gz">cdrskin-1.5.6.tar.gz</A>
(1060 KB). (1075 KB).
</DD> </DD>
<DD><A HREF="cdrskin-1.5.2.tar.gz.sig">cdrskin-1.5.2.tar.gz.sig</A></DD> <DD><A HREF="cdrskin-1.5.6.tar.gz.sig">cdrskin-1.5.6.tar.gz.sig</A></DD>
<DD> <DD>
(detached GPG signature for verification by (detached GPG signature for verification by
<KBD>gpg --verify cdrskin-1.5.2.tar.gz.sig cdrskin-1.5.2.tar.gz</KBD> <KBD>gpg --verify cdrskin-1.5.6.tar.gz.sig cdrskin-1.5.6.tar.gz</KBD>
<BR> <BR>
after <KBD>gpg --keyserver keys.gnupg.net --recv-keys ABC0A854</KBD>). after <KBD>gpg --keyserver keyserver.ubuntu.com --recv-keys ABC0A854</KBD>).
</DD> </DD>
<DD> <DD>
The cdrskin tarballs are source code identical with libburn releases The cdrskin tarballs are source code identical with libburn releases
@ -259,48 +259,35 @@ cdrskin_0.4.2.pl00-x86-suse9_0-static.tar.gz</A>, (310 KB), -static compiled,
<HR> <HR>
<P> <P>
Enhancements towards previous stable version cdrskin-1.5.0: Enhancements towards previous stable version cdrskin-1.5.4:
<UL> <UL>
<LI>New cdrskin option --list_features</LI> <LI>New cdrskin option --bdr_obs_exempt</LI>
<LI>Officially enabled overburning on CD media</LI>
<!-- <!--
<LI>none</LI> <LI>none</LI>
--> -->
</UL> </UL>
Bug fixes towards cdrskin-1.5.0: Bug fixes towards cdrskin-1.5.4:
<UL> <UL>
<LI> <LI>Overburning with cdrskin option -force ended by a libburn error</LI>
No lock was obtained for setting up a fifo object
</LI>
<LI>
TDK Corporation was not recognized as manufacturer of DVD-R "TTH02"
</LI>
<LI>
Stream recording was applied regardless whether the drive offers it.
This caused Xfburn failures with some MATSHITA laptop drives.
</LI>
</UL> </UL>
<!-- <!--
<LI>none</LI>
Bug fixes towards cdrskin-1.4.2 (without .pl01):
<UL>
</UL>
--> -->
<HR> <HR>
<P> <P>
<DL> <DL>
<DT><H3>Development snapshot, version 1.5.3 :</H3></DT> <DT><H3>Development snapshot, version 1.5.7 :</H3></DT>
<DD>Enhancements towards current stable version 1.5.2: <DD>Enhancements towards current stable version 1.5.6:
<UL> <UL>
<LI>none yet</LI> <LI>none yet</LI>
<!-- <!--
<LI>none yet</LI>
--> -->
</UL> </UL>
</DD> Bug fixes towards cdrskin-1.5.6:
<DD>Bug fixes towards cdrskin-1.5.2:
<UL> <UL>
<LI>none yet</LI> <LI>none yet</LI>
<!-- <!--
@ -310,14 +297,15 @@ Bug fixes towards cdrskin-1.4.2 (without .pl01):
</DD> </DD>
<DD>&nbsp;</DD> <DD>&nbsp;</DD>
<DD><A HREF="README_cdrskin_devel">README 1.5.3</A> <DD><A HREF="README_cdrskin_devel">README 1.5.7</A>
<DD><A HREF="cdrskin__help_devel">cdrskin-1.5.3 --help</A></DD> <DD><A HREF="cdrskin__help_devel">cdrskin-1.5.7 --help</A></DD>
<DD><A HREF="cdrskin_help_devel">cdrskin-1.5.3 -help</A></DD> <DD><A HREF="cdrskin_help_devel">cdrskin-1.5.7 -help</A></DD>
<DD><A HREF="man_1_cdrskin_devel.html">man cdrskin (as of 1.5.3)</A></DD> <DD><A HREF="man_1_cdrskin_devel.html">man cdrskin (as of 1.5.7)</A></DD>
<DD>&nbsp;</DD> <DD>&nbsp;</DD>
<DT>Maintainers of cdrskin unstable packages please use SVN of <DT>Maintainers of cdrskin unstable packages please use git of
<A HREF="http://libburnia-project.org"> libburnia-project.org</A></DT> <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> <DD>Download: <KBD>
<B>git clone https://dev.lovelyhq.com/libburnia/libburn.git</B>
</KBD></DD> </KBD></DD>
<DD>Build: <KBD><B>cd libburn ; ./bootstrap ; ./configure --prefix /usr ; make ; cdrskin/compile_cdrskin.sh</B> <DD>Build: <KBD><B>cd libburn ; ./bootstrap ; ./configure --prefix /usr ; make ; cdrskin/compile_cdrskin.sh</B>
</KBD></DD> </KBD></DD>
@ -333,8 +321,8 @@ admins with full system sovereignty.</DT>
<A HREF="README_cdrskin_devel">upcoming README</A> ): <A HREF="README_cdrskin_devel">upcoming README</A> ):
</DD> </DD>
<DD> <DD>
<A HREF="cdrskin-1.5.3.tar.gz">cdrskin-1.5.3.tar.gz</A> <A HREF="cdrskin-1.5.7.tar.gz">cdrskin-1.5.7.tar.gz</A>
(1060 KB). (1075 KB).
</DD> </DD>
<!-- This is not offered any more since spring 2008 <!-- This is not offered any more since spring 2008
@ -509,7 +497,7 @@ opportunity is the goal of a cdrecord compatibility wrapper.
<BR> <BR>
<BR> <BR>
It is very important to me that this project is not perceived as hostile It is very important to me that this project is not perceived as hostile
towards Joerg Schilling and his ongoing work. towards Joerg Schilling and his work.
I owe him much. For cdrecord, for mkisofs, for star. Chapeau. I owe him much. For cdrecord, for mkisofs, for star. Chapeau.
<BR> <BR>
</P> </P>

View File

@ -1 +1 @@
#define Cdrskin_timestamP "2019.10.26.143001" #define Cdrskin_timestamP "2024.04.27.162735"

View File

@ -13931,7 +13931,7 @@ ChangeLog
cdrskin/changelog.txt cdrskin/changelog.txt
Updated change log Updated change log
26 Oct 2019 [] 26 Oct 2019 [3a94030]
libburn/mmc.h libburn/mmc.h
cdrskin/changelog.txt cdrskin/changelog.txt
Committed forgotten header file Committed forgotten header file
@ -13945,13 +13945,329 @@ Committed forgotten header file
* New cdrskin option --list_features * New cdrskin option --list_features
2019.10.27.142135 [0a37e8c]
Makefile.am
configure.ac
libburn/libburn.h
cdrskin/cdrskin.c
cdrskin/cdrskin.1
cdrskin/README
cdrskin/cdrskin_timestamp.h
Made number transition to 1.5.3
27 Oct 2019 [95ad059]
ChangeLog
cdrskin/changelog.txt
Updated change log
------------------------------------ cycle - cdrskin-1.5.3 - 2019.10.27.142135
27 Oct 2019 [1c235e8]
cdrskin/cdrskin.1
Corrected alphabetical sort rank of --list_features in man cdrskin
2019.10.28.155736 [ba9b69b]
libburn/libdax_audioxtr.c
libburn/async.c
libburn/libdax_msgs.h
libburn/file.c
libburn/options.c
libburn/spc.c
libburn/structure.h
libburn/sector.c
libburn/libdax_audioxtr.h
libburn/transport.h
libburn/sg-dummy.c
libburn/sg-linux.c
libburn/sg-netbsd.c
libburn/cdtext.c
libburn/drive.c
libburn/init.c
libburn/write.c
libburn/read.c
libburn/libburn.h
libburn/options.h
libburn/mmc.c
libburn/ddlpa.c
libburn/sg-solaris.c
libburn/ecma130ab.c
libburn/sg-libcdio.c
libburn/sg-freebsd-port.c
libburn/init.h
Fixed spelling errors found by fossies.org with codespell
2019.11.25.091234 [91f7d4d] [release-1.5.2.pl01 30c9f6d]
configure.ac
libburn/sg-linux.c
cdrskin/cdrfifo.c
Bug fix: cdrskin multi-track burning was slow and stalled after track 1.
Regression introduced in version 1.5.0 by commit 84fad99, 2018.02.05
[] []
ChangeLog ChangeLog
cdrskin/cdrskin_eng.html cdrskin/cdrskin_eng.html
cdrskin/changelog.txt cdrskin/changelog.txt
Updated change log Updated change log
------------------------------------ cycle - cdrskin-1.5.1 - 25 Nov 2019 [branch-1.5.2.pl01 4c0ebf1]
README
cdrskin/README
ChangeLog
cdrskin/changelog.txt
cdrskin/cdrskin_eng.html
Mentioned bug fix and pl01
25 Nov 2019 [d4593f4]
README
Updated README about 1.5.2.pl01
---------------------- bug fix release - cdrskin-1.5.2.pl01 - 2019.11.25.094931
------------------------------------ cycle - cdrskin-1.5.3 - 2019.11.25.194241
* Bug fix: cdrskin multi-track burning was slow and stalled after track 1.
Regression introduced in version 1.5.0 by commit 84fad99, 2018.02.05
O_DIRECT is now disabled for track sources.
26 Nov 2019 [b57c05c]
configure.ac
Incremented .so numbering to libburn.so.4.106.0
2020.04.15.185125 [7991750]
libburn/sg-linux.c
Bug fix: Early SCSI commands from sg-linux.c were not logged
11 Jul 2020 [e09acf3]
cdrskin/cdrskin.1
Corrected a typo in man cdrskin found by lintian
2020.08.22.132046 [8d934ee]
libburn/transport.h
libburn/drive.c
libburn/write.c
libburn/sg-linux.c
Testing use of experimental ioctl CDROM_REVALIDATE after media state changes
2020.08.22.132046 [8d934ee]
libburn/transport.h
libburn/drive.c
libburn/write.c
libburn/sg-linux.c
Testing use of experimental ioctl CDROM_REVALIDATE after media state changes
2020.08.24.132739 [0e1f5dc]
libburn/libburn.h
libburn/libburn.ver
libburn/transport.h
libburn/drive.c
libburn/mmc.c
New API call burn_drive_set_speed_exact()
2020.08.26.140343 [8b9a8cf]
libburn/libburn.h
libburn/libburn.ver
libburn/write.c
New API call burn_nominal_slowdown()
2020.09.20.084444 [ab6b103]
libburn/sg-linux.c
Changed experimental ioctl from CDROM_REVALIDATE to CDROM_SIMUL_CHANGE
2020.09.20.204320 [9bc9900]
libburn/sg-linux.c
For now using CDROM_SIMUL_CHANGE only if -DLibburn_use_linux_ioctl_simul_changE
2020.09.30.185335 [3468a2a]
libburn/spc.c
Tolerating all sense replies of form 6,28,*
2021.01.30.103001 [2a58d5a]
Makefile.am
configure.ac
README
libburn/libburn.h
cdrskin/cdrskin.c
cdrskin/cdrskin.1
cdrskin/README
cdrskin/compile_cdrskin.sh
cdrskin/cdrskin_timestamp.h
cdrskin/cdrskin_eng.html
Made number transition to 1.5.4
30 Jan 2021 [d95d5a2]
- cdrskin/add_ts_changes_to_libburn_1_5_2
- cdrskin/add_ts_changes_to_libburn_1_5_3
+ cdrskin/add_ts_changes_to_libburn_1_5_4
+ cdrskin/add_ts_changes_to_libburn_1_5_5
Updated cdrskin tarball generator
30 Jan 2021 [d146886]
configure.ac
Corrected SONAME parameters to produce libburn.so.4.107.0
30 Jan 2021 [d3bd97c]
ChangeLog
cdrskin/cdrskin_eng.html
cdrskin/changelog.txt
Updated change log
----------------------------------- release - cdrskin-1.5.4 - 2021.01.30.103001
* Bug fix: Early SCSI commands from sg-linux.c were not logged
* New API call burn_drive_set_speed_exact()
* New API call burn_nominal_slowdown()
2021.01.30.153517 [f1d5c67]
Makefile.am
configure.ac
libburn/libburn.h
cdrskin/cdrskin.c
cdrskin/cdrskin.1
cdrskin/README
cdrskin/cdrskin_timestamp.h
Made number transition to 1.5.5
2021.02.28.121708 [2a977cf]
libburn/libdax_msgs.h
libburn/structure.c
libburn/write.c
libburn/sector.c
Improved error message if a track is larger than 4 TiB - 32 KiB
2021.02.28.121943 [31e8f5c]
libburn/transport.h
libburn/drive.h
libburn/drive.c
Unified size of large or unlimited pseudo drives to 4 TiB - 32 KiB
2021.03.12.082731 [892df64]
acinclude.m4
Made optional the use of libcam and thus SCSI passthrough on GNU/FreeBSD systems
02 Sep 2021 [8d270b1]
configure.ac
Removed unneeded configure.ac macro AC_C_BIGENDIAN
02 Sep 2021 [c76145f]
cdrskin/cdrskin.1
Corrected man page about the default of extract_basename=
02 Sep 2021 [0a1bbb1]
Makefile.am
Added doc/waveformat.txt to libburn tarball
2021.09.02.181259 [27e1568]
libburn/mmc.c
Let mmc_read_cd() for CD-DA set command.dxfer_len
2021.09.12.084139 [31591b8]
libburn/libburn.h
libburn/options.h
libburn/options.c
libburn/write.c
libburn/libburn.ver
New API call burn_write_opts_set_bdr_obs_exempt()
2021.09.12.084556 [da44c70]
cdrskin/cdrskin.c
cdrskin/cdrskin.1
New cdrskin option --bdr_obs_exempt
2021.11.24.114417 [7765fbd]
libburn/libburn.h
libburn/mmc.c
Enabled overburning with burn_write_opts_set_force(,1)
24 Nov 2021 [d4d6321]
cdrskin/cdrskin.1
Improved man page of cdrskin about -force after enabling overburning in libburn
25 Nov 2021 [879cb99]
ChangeLog
cdrskin/cdrskin_eng.html
cdrskin/changelog.txt
Updated change log
------------------------------------ cycle - cdrskin-1.5.5 - 2021.11.25.094022
* New API call burn_write_opts_set_bdr_obs_exempt()
* New cdrskin option --bdr_obs_exempt
* Enabled overburning with burn_write_opts_set_force(,1)
* Bug fix: Overburning with cdrskin option -force ended by a libburn error
2022.04.05.135930 [629a4fa]
cdrskin/cdrskin.c
Let cdrskin take options -VV and -VVV as -V
2022.04.05.140409 [1954514]
cdrskin/cdrskin.c
Updated copyright dates of cdrskin
2022.12.10.093508 [a904ae9]
cdrskin/cdrskin.c
Enlarged maximum allowed tsize= value to 4 TiB - 2 KiB (just in case)
2023.06.07.143001 [1172ef7]
Makefile.am
configure.ac
README
libburn/libburn.h
cdrskin/cdrskin.c
cdrskin/cdrskin.1
cdrskin/README
cdrskin/compile_cdrskin.sh
cdrskin/cdrskin_timestamp.h
cdrskin/cdrskin_eng.html
Made number transition to 1.5.6
07 Jun 2023 [9acb8ad]
- cdrskin/add_ts_changes_to_libburn_1_5_4
- cdrskin/add_ts_changes_to_libburn_1_5_5
+ cdrskin/add_ts_changes_to_libburn_1_5_6
+ cdrskin/add_ts_changes_to_libburn_1_5_7
Updated cdrskin tarball generator
07 Jun 2023 [f795db5]
cdrskin/cdrskin_eng.html
Last minute correction in cdrskin web page
07 Jun 2023 [4628231]
ChangeLog
cdrskin/changelog.txt
Updated change log
----------------------------------- release - cdrskin-1.5.6 - 2023.06.07.143001
* New API call burn_write_opts_set_bdr_obs_exempt()
* New cdrskin option --bdr_obs_exempt
* Enabled overburning with burn_write_opts_set_force(,1)
* Bug fix: Overburning with cdrskin option -force ended by a libburn error
2023.06.07.183206 []
Makefile.am
configure.ac
libburn/libburn.h
cdrskin/cdrskin.c
cdrskin/cdrskin.1
cdrskin/README
cdrskin/cdrskin_timestamp.h
Made number transition to 1.5.7
07 Jun 2023 []
ChangeLog
cdrskin/changelog.txt
Updated change log
[]
libburn/cleanup.c
>>> SIGCONT in non_signal_list : local but not in git
------------------------------------ cycle - cdrskin-1.5.7 -
------------------------------------ cycle - cdrskin-1.5.7 -
((( (((
[] []

View File

@ -1,14 +1,14 @@
#!/bin/sh #!/bin/sh
# compile_cdrskin.sh # compile_cdrskin.sh
# Copyright 2005 - 2019 Thomas Schmitt, scdbackup@gmx.net, GPL v2 or later # Copyright 2005 - 2023 Thomas Schmitt, scdbackup@gmx.net, GPL v2 or later
# to be executed within ./libburn-* or./cdrskin-* # to be executed within ./libburn-* or./cdrskin-*
debug_opts="-O2" debug_opts="-O2"
def_opts= def_opts=
largefile_opts="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1" largefile_opts="-D_FILE_OFFSET_BITS=64 -D_LARGEFILE_SOURCE=1"
fifo_opts="" fifo_opts=""
libvers="-DCdrskin_libburn_1_5_2" libvers="-DCdrskin_libburn_1_5_6"
# To be used if Makefile.am uses libburn_libburn_la_CFLAGS # To be used if Makefile.am uses libburn_libburn_la_CFLAGS
# burn="libburn/libburn_libburn_la-" # burn="libburn/libburn_libburn_la-"
@ -41,15 +41,15 @@ do
elif test "$i" = "-compile_dewav" elif test "$i" = "-compile_dewav"
then then
compile_dewav=1 compile_dewav=1
elif test "$i" = "-libburn_1_5_2" elif test "$i" = "-libburn_1_5_6"
then then
libvers="-DCdrskin_libburn_1_5_2" libvers="-DCdrskin_libburn_1_5_6"
libdax_audioxtr_o="$burn"libdax_audioxtr.o libdax_audioxtr_o="$burn"libdax_audioxtr.o
libdax_msgs_o="$burn"libdax_msgs.o libdax_msgs_o="$burn"libdax_msgs.o
cleanup_src_or_obj="$burn"cleanup.o cleanup_src_or_obj="$burn"cleanup.o
elif test "$i" = "-libburn_svn" elif test "$i" = "-libburn_svn"
then then
libvers="-DCdrskin_libburn_1_5_3" libvers="-DCdrskin_libburn_1_5_7"
libdax_audioxtr_o="$burn"libdax_audioxtr.o libdax_audioxtr_o="$burn"libdax_audioxtr.o
libdax_msgs_o="$burn"libdax_msgs.o libdax_msgs_o="$burn"libdax_msgs.o
cleanup_src_or_obj="$burn"cleanup.o cleanup_src_or_obj="$burn"cleanup.o
@ -99,8 +99,8 @@ do
echo "Options:" echo "Options:"
echo " -compile_cdrfifo compile program cdrskin/cdrfifo." echo " -compile_cdrfifo compile program cdrskin/cdrfifo."
echo " -compile_dewav compile program test/dewav without libburn." echo " -compile_dewav compile program test/dewav without libburn."
echo " -libburn_1_5_2 set macro to match libburn-1.5.2" echo " -libburn_1_5_6 set macro to match libburn-1.5.6"
echo " -libburn_svn set macro to match current libburn-SVN." echo " -libburn_svn set macro to match current libburn git."
echo " -dvd_obs_64k 64 KB default size for DVD/BD writing." echo " -dvd_obs_64k 64 KB default size for DVD/BD writing."
echo " -use_libcdio link with -lcdio because libburn uses it." echo " -use_libcdio link with -lcdio because libburn uses it."
echo " -do_not_compile_cdrskin omit compilation of cdrskin/cdrskin." echo " -do_not_compile_cdrskin omit compilation of cdrskin/cdrskin."

View File

@ -1,4 +1,4 @@
AC_INIT([libburn], [1.5.2], [http://libburnia-project.org]) AC_INIT([libburn], [1.5.7], [http://libburnia-project.org])
AC_PREREQ([2.50]) AC_PREREQ([2.50])
dnl AC_CONFIG_HEADER([config.h]) dnl AC_CONFIG_HEADER([config.h])
@ -112,6 +112,8 @@ dnl 1.4.6 = libburn.so.4.99.0
dnl 1.4.8 = libburn.so.4.101.0 dnl 1.4.8 = libburn.so.4.101.0
dnl 1.5.0 = libburn.so.4.103.0 dnl 1.5.0 = libburn.so.4.103.0
dnl 1.5.2 = libburn.so.4.105.0 dnl 1.5.2 = libburn.so.4.105.0
dnl 1.5.4 = libburn.so.4.107.0
dnl 1.5.6 = libburn.so.4.109.0
dnl dnl
dnl So LT_CURRENT, LT_REVISION and LT_AGE get set directly here. 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 SONAME of the emerging library is LT_CURRENT - LT_AGE.
@ -137,7 +139,7 @@ dnl
dnl As said: Only copies. Original in libburn/libburn.h : burn_header_version_* dnl As said: Only copies. Original in libburn/libburn.h : burn_header_version_*
BURN_MAJOR_VERSION=1 BURN_MAJOR_VERSION=1
BURN_MINOR_VERSION=5 BURN_MINOR_VERSION=5
BURN_MICRO_VERSION=2 BURN_MICRO_VERSION=7
BURN_VERSION=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION BURN_VERSION=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION
AC_SUBST(BURN_MAJOR_VERSION) AC_SUBST(BURN_MAJOR_VERSION)
@ -148,14 +150,14 @@ AC_SUBST(BURN_VERSION)
dnl Libtool versioning dnl Libtool versioning
LT_RELEASE=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION LT_RELEASE=$BURN_MAJOR_VERSION.$BURN_MINOR_VERSION.$BURN_MICRO_VERSION
dnl dnl
dnl This is the release version libburn-1.5.2 dnl ### This is the release version libburn-1.5.6
dnl ### This is the development version after above release version 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 not yet happened.
dnl ### LT_CURRENT++, LT_AGE++ has happened meanwhile. dnl LT_CURRENT++, LT_AGE++ has happened meanwhile.
dnl dnl
dnl SONAME = 109 - 105 = 4 . Linux library name = libburn.so.4.105.0 dnl SONAME = 114 - 110 = 4 . Linux library name = libburn.so.4.110.0
LT_CURRENT=109 LT_CURRENT=114
LT_AGE=105 LT_AGE=110
LT_REVISION=0 LT_REVISION=0
LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE` LT_CURRENT_MINUS_AGE=`expr $LT_CURRENT - $LT_AGE`
@ -180,7 +182,6 @@ dnl AM_MAINTAINER_MODE
AM_PROG_CC_C_O AM_PROG_CC_C_O
AC_C_CONST AC_C_CONST
AC_C_INLINE AC_C_INLINE
AC_C_BIGENDIAN
dnl Large file support dnl Large file support
AC_SYS_LARGEFILE AC_SYS_LARGEFILE
@ -218,11 +219,12 @@ CFLAGS="$STATVFS_DEF $CFLAGS"
dnl ts A91122 dnl ts A91122
AC_ARG_ENABLE(track-src-odirect, AC_ARG_ENABLE(track-src-odirect,
[ --enable-track-src-odirect Enable use of O_DIRECT with track input, default=no], [ --enable-track-src-odirect Banned for now: (Enable use of O_DIRECT with track input, default=no)],
, enable_track_src_odirect=no) , enable_track_src_odirect=no)
if test x$enable_track_src_odirect = xyes; then if test x$enable_track_src_odirect = xyes; then
LIBBURN_O_DIRECT_DEF="-DLibburn_read_o_direcT" # LIBBURN_O_DIRECT_DEF="-DLibburn_read_o_direcT"
echo "enabled use of O_DIRECT with track input" # echo "enabled use of O_DIRECT with track input"
echo "REFUSED to enable use of O_DIRECT with track input because of cdrskin multi-track bug"
else else
LIBBURN_O_DIRECT_DEF= LIBBURN_O_DIRECT_DEF=
echo "disabled use of O_DIRECT with track input" echo "disabled use of O_DIRECT with track input"

View File

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2017 Thomas Schmitt <scdbackup@gmx.net> Copyright (c) 2006 - 2024 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later. Provided under GPL version 2 or later.
*/ */
@ -279,7 +279,7 @@ static void *scan_worker_func(struct w_list *w)
} }
static void reset_progress(struct burn_drive *d, int sessions, int tracks, static void reset_progress(struct burn_drive *d, int sessions, int tracks,
int indices, int sectors, int flag) int indices, off_t sectors, int flag)
{ {
/* reset the progress indicator */ /* reset the progress indicator */
d->progress.session = 0; d->progress.session = 0;
@ -412,14 +412,14 @@ void burn_disc_erase(struct burn_drive *drive, int fast)
return; return;
} }
reset_progress(drive, 1, 1, 1, 0x10000, 0); reset_progress(drive, 1, 1, 1, (off_t) 0x10000, 0);
/* A70103 : will be set to 0 by burn_disc_erase_sync() */ /* A70103 : will be set to 0 by burn_disc_erase_sync() */
drive->cancel = 1; drive->cancel = 1;
/* ts A70103 moved up from burn_disc_erase_sync() */ /* ts A70103 moved up from burn_disc_erase_sync() */
/* ts A60825 : allow on parole to blank appendable CDs */ /* ts A60825 : allow on parole to blank appendable CDs */
/* ts A70131 : allow blanking of overwriteable DVD-RW (profile 0x13) */ /* ts A70131 : allow blanking of overwritable DVD-RW (profile 0x13) */
/* ts A70216 : allow blanking of CD-RW or DVD-RW in any regular state /* ts A70216 : allow blanking of CD-RW or DVD-RW in any regular state
and of any kind of full media */ and of any kind of full media */
/* ts A70909 : the willingness to burn any BURN_DISC_FULL media is /* ts A70909 : the willingness to burn any BURN_DISC_FULL media is
@ -494,7 +494,7 @@ void burn_disc_format(struct burn_drive *drive, off_t size, int flag)
int ok = 0, ret; int ok = 0, ret;
char msg[40]; char msg[40];
reset_progress(drive, 1, 1, 1, 0x10000, 0); reset_progress(drive, 1, 1, 1, (off_t) 0x10000, 0);
if ((SCAN_GOING()) || find_worker(drive) != NULL) { if ((SCAN_GOING()) || find_worker(drive) != NULL) {
libdax_msgs_submit(libdax_messenger, drive->global_index, libdax_msgs_submit(libdax_messenger, drive->global_index,
@ -652,7 +652,7 @@ void burn_disc_write(struct burn_write_opts *opts, struct burn_disc *disc)
} }
reset_progress(d, disc->sessions, disc->session[0]->tracks, reset_progress(d, disc->sessions, disc->session[0]->tracks,
disc->session[0]->track[0]->indices, 0, 0); disc->session[0]->track[0]->indices, (off_t) 0, 0);
/* For the next lines any return indicates failure */ /* For the next lines any return indicates failure */
d->cancel = 1; d->cancel = 1;

View File

@ -77,7 +77,7 @@ int burn_create_new_pack(int pack_type, int track_no, int double_byte,
/* Plain implementation of polynomial division on a Galois field, where /* Plain implementation of polynomial division on a Galois field, where
addition and subtraction both are binary exor. Euclidian algorithm. addition and subtraction both are binary exor. Euclidean algorithm.
Divisor is x^16 + x^12 + x^5 + 1 = 0x11021. Divisor is x^16 + x^12 + x^5 + 1 = 0x11021.
*/ */
static int crc_11021(unsigned char *data, int count, int flag) static int crc_11021(unsigned char *data, int count, int flag)

View File

@ -12,7 +12,7 @@
-DDDLPA_C_STANDALONE -o ddlpa ddlpa.c -DDDLPA_C_STANDALONE -o ddlpa ddlpa.c
The system macros enable 64-bit off_t and open(2) flag O_LARGEFILE, which 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 are not absolutely necessary but explicitly take into respect that
our devices can offer more than 2 GB of addressable data. our devices can offer more than 2 GB of addressable data.
Run test program: Run test program:

View File

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2017 Thomas Schmitt <scdbackup@gmx.net> Copyright (c) 2006 - 2024 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later. Provided under GPL version 2 or later.
*/ */
@ -191,7 +191,7 @@ int burn_drive_is_released(struct burn_drive *d)
/* ts A60906 */ /* ts A60906 */
/** Inquires drive status in respect to degree of app usage. /** Inquires drive status in respect to degree of app usage.
@param return -2 = drive is forgotten @param return -2 = drive is forgotten
-1 = drive is closed (i.e. released explicitely) -1 = drive is closed (i.e. released explicitly)
0 = drive is open, not grabbed (after scan, before 1st grab) 0 = drive is open, not grabbed (after scan, before 1st grab)
1 = drive is grabbed but BURN_DRIVE_IDLE 1 = drive is grabbed but BURN_DRIVE_IDLE
2 = drive is grabbed, synchronous read/write interrupted 2 = drive is grabbed, synchronous read/write interrupted
@ -287,7 +287,7 @@ int burn_drive_inquire_media(struct burn_drive *d)
/* ts A61020 : d->status was set to BURN_DISC_BLANK as pure guess */ /* ts A61020 : d->status was set to BURN_DISC_BLANK as pure guess */
/* ts A71128 : run read_disc_info() for any recognizeable profile */ /* ts A71128 : run read_disc_info() for any recognizable profile */
if (d->current_profile > 0 || d->current_is_guessed_profile || if (d->current_profile > 0 || d->current_is_guessed_profile ||
(d->mdata->p2a_valid > 0 && (d->mdata->p2a_valid > 0 &&
(d->mdata->cdr_write || d->mdata->cdrw_write || (d->mdata->cdr_write || d->mdata->cdrw_write ||
@ -375,8 +375,8 @@ static int burn_drive__is_rdwr(char *fname, int *stat_ret,
else if (is_rdwr) else if (is_rdwr)
ret = burn_os_stdio_capacity(fname, 0, &read_size); ret = burn_os_stdio_capacity(fname, 0, &read_size);
if (ret <= 0 || if (ret <= 0 ||
read_size / (off_t) 2048 >= (off_t) 0x7ffffff0) read_size >= BURN_DRIVE_MAX_BYTES)
read_size = (off_t) 0x7ffffff0 * (off_t) 2048; read_size = BURN_DRIVE_MAX_BYTES;
} }
if (is_rdwr && fd >= 0) { if (is_rdwr && fd >= 0) {
@ -451,10 +451,10 @@ int burn_drive_grab_stdio(struct burn_drive *d, int flag)
if (stat_ret != -1 && S_ISREG(stbuf.st_mode) && if (stat_ret != -1 && S_ISREG(stbuf.st_mode) &&
stbuf.st_size > 0) { stbuf.st_size > 0) {
d->status = BURN_DISC_APPENDABLE; d->status = BURN_DISC_APPENDABLE;
if (stbuf.st_size / (off_t) 2048 if (stbuf.st_size >= BURN_DRIVE_MAX_BYTES) {
>= 0x7ffffff0) {
d->status = BURN_DISC_FULL; d->status = BURN_DISC_FULL;
d->role_5_nwa = 0x7ffffff0; d->role_5_nwa = (off_t) BURN_DRIVE_MAX_BYTES /
(off_t) 2048;
} else } else
d->role_5_nwa = stbuf.st_size / 2048 + d->role_5_nwa = stbuf.st_size / 2048 +
!!(stbuf.st_size % 2048); !!(stbuf.st_size % 2048);
@ -556,6 +556,9 @@ struct burn_drive *burn_drive_register(struct burn_drive *d)
d->thread_pid = 0; d->thread_pid = 0;
d->thread_pid_valid = 0; d->thread_pid_valid = 0;
memset(&(d->thread_tid), 0, sizeof(d->thread_tid)); memset(&(d->thread_tid), 0, sizeof(d->thread_tid));
d->medium_state_changed = 0;
d->set_streaming_exact_bit = 0;
d->set_streaming_err = 0;
d->toc_entries = 0; d->toc_entries = 0;
d->toc_entry = NULL; d->toc_entry = NULL;
d->disc = NULL; d->disc = NULL;
@ -883,6 +886,7 @@ void burn_disc_erase_sync(struct burn_drive *d, int fast)
d->progress.sector = 0; d->progress.sector = 0;
#endif /* Libburn_reset_progress_asynC */ #endif /* Libburn_reset_progress_asynC */
d->medium_state_changed = 1;
d->erase(d, fast); d->erase(d, fast);
d->busy = BURN_DRIVE_ERASING; d->busy = BURN_DRIVE_ERASING;
@ -972,6 +976,7 @@ void burn_disc_format_sync(struct burn_drive *d, off_t size, int flag)
stages = 1 + ((flag & 1) && size > 1024 * 1024); stages = 1 + ((flag & 1) && size > 1024 * 1024);
d->cancel = 0; d->cancel = 0;
d->busy = BURN_DRIVE_FORMATTING; d->busy = BURN_DRIVE_FORMATTING;
d->medium_state_changed = 1;
ret = d->format_unit(d, size, flag & 0xfff6); /* forward bits */ ret = d->format_unit(d, size, flag & 0xfff6); /* forward bits */
if (ret <= 0) if (ret <= 0)
@ -1131,12 +1136,13 @@ int burn_disc_erasable(struct burn_drive *d)
{ {
return d->erasable; return d->erasable;
} }
enum burn_drive_status burn_drive_get_status(struct burn_drive *d,
struct burn_progress *p)
void burn_drive_get_status_sig_handling(void)
{ {
/* --- Part of asynchronous signal handling --- */ /* --- Part of asynchronous signal handling --- */
/* This frequently used call may be used to react on messages from /* The frequently used call burn_drive_get_status*() may be used
the libburn built-in signal handler. to react on messages from the libburn built-in signal handler.
*/ */
/* ts B00225 : /* ts B00225 :
@ -1160,11 +1166,61 @@ enum burn_drive_status burn_drive_get_status(struct burn_drive *d,
} }
/* --- End of asynchronous signal handling --- */ /* --- End of asynchronous signal handling --- */
}
enum burn_drive_status burn_drive_get_status(struct burn_drive *d,
struct burn_progress *p)
{
burn_drive_get_status_sig_handling();
if (p != NULL) { if (p != NULL) {
memcpy(p, &(d->progress), sizeof(struct burn_progress));
/* TODO: add mutex */ /* TODO: add mutex */
p->sessions = d->progress.sessions;
p->session = d->progress.session;
p->tracks = d->progress.tracks;
p->track = d->progress.track;
p->indices = d->progress.indices;
p->index = d->progress.index;
if(d->progress.start_sector < 0x80000000)
p->start_sector = d->progress.start_sector;
else
p->start_sector = 0x7fffffff;
if(d->progress.sectors < 0x80000000)
p->sectors = d->progress.sectors;
else
p->sectors = 0x7fffffff;
if(d->progress.sector < 0x80000000)
p->sector = d->progress.sector;
else
p->sector = 0x7fffffff;
if(d->progress.buffer_capacity < 0x100000000)
p->buffer_capacity = d->progress.buffer_capacity;
else
p->buffer_capacity = 0xffffffff;
if(d->progress.buffer_available < 0x100000000)
p->buffer_available = d->progress.buffer_available;
else
p->buffer_available = 0xffffffff;
p->buffered_bytes = d->progress.buffered_bytes;
if(d->progress.buffer_min_fill < 0x100000000)
p->buffer_min_fill = d->progress.buffer_min_fill;
else
p->buffer_min_fill = 0xffffffff;
}
return d->busy;
}
enum burn_drive_status burn_drive_get_status_v2(struct burn_drive *d,
struct burn_progress_v2 *p)
{
burn_drive_get_status_sig_handling();
if (p != NULL) {
/* TODO: add mutex */
memcpy(p, &(d->progress), sizeof(struct burn_progress_v2));
} }
return d->busy; return d->busy;
} }
@ -1327,7 +1383,7 @@ static int drive_getcaps(struct burn_drive *d, struct burn_drive_info *out)
/* ts A91112 */ /* ts A91112 */
/* Set default block types. The call d->probe_write_modes() is quite /* Set default block types. The call d->probe_write_modes() is quite
obtrusive. It may be performed explicitely by new API call obtrusive. It may be performed explicitly by new API call
burn_drive_probe_cd_write_modes(). burn_drive_probe_cd_write_modes().
*/ */
if (out->write_dvdram || out->write_dvdr || if (out->write_dvdram || out->write_dvdr ||
@ -1426,7 +1482,7 @@ int burn_drive_scan_sync(struct burn_drive_info *drives[],
*n_drives = 0; *n_drives = 0;
/* ts A70907 : wether to scan from scratch or to extend */ /* ts A70907 : whether to scan from scratch or to extend */
for (i = 0; i < (int) sizeof(scanned); i++) for (i = 0; i < (int) sizeof(scanned); i++)
scanned[i] = 0; scanned[i] = 0;
if (flag & 1) { if (flag & 1) {
@ -1567,7 +1623,7 @@ void burn_drive_info_free(struct burn_drive_info drive_infos[])
/* ts A70903 : THIS IS WRONG ! (disabled now) /* ts A70903 : THIS IS WRONG ! (disabled now)
It endangers multi drive usage. It endangers multi drive usage.
This call is not entitled to delete all drives, only the This call is not entitled to delete all drives, only the
ones of the array which it receives a parmeter. ones of the array which it receives a parameter.
Problem: It was unclear how many items are listed in drive_infos Problem: It was unclear how many items are listed in drive_infos
Solution: Added a end marker element to any burn_drive_info array Solution: Added a end marker element to any burn_drive_info array
@ -1596,6 +1652,22 @@ void burn_drive_set_speed(struct burn_drive *d, int r, int w)
d->set_speed(d, r, w); d->set_speed(d, r, w);
} }
int burn_drive_set_speed_exact(struct burn_drive *d, int r, int w)
{
int sose;
d->nominal_write_speed = w;
if(d->drive_role != 1)
return 0;
sose = d->silent_on_scsi_error;
d->silent_on_scsi_error = 3;
d->set_streaming_err = 0;
d->set_streaming_exact_bit = 1;
d->set_speed(d, r, w);
d->silent_on_scsi_error = sose;
d->set_streaming_exact_bit = 0;
return !d->set_streaming_err;
}
/* ts A70711 API function */ /* ts A70711 API function */
int burn_drive_set_buffer_waiting(struct burn_drive *d, int enable, int burn_drive_set_buffer_waiting(struct burn_drive *d, int enable,
@ -1761,8 +1833,7 @@ int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname)
{ {
int ret = -1, role = 0, fd; int ret = -1, role = 0, fd;
int is_rdwr = 0, stat_ret = -1; int is_rdwr = 0, stat_ret = -1;
/* divided by 512 it needs to fit into a signed long integer */ off_t size = BURN_DRIVE_MAX_BYTES;
off_t size = ((off_t) (512 * 1024 * 1024 - 1) * (off_t) 2048);
off_t read_size = -1; off_t read_size = -1;
struct burn_drive *d= NULL, *regd_d; struct burn_drive *d= NULL, *regd_d;
struct stat stbuf; struct stat stbuf;
@ -1838,10 +1909,11 @@ int burn_drive_grab_dummy(struct burn_drive_info *drive_infos[], char *fname)
(burn_drive_role_4_allowed & 8)) { (burn_drive_role_4_allowed & 8)) {
d->status = BURN_DISC_APPENDABLE; d->status = BURN_DISC_APPENDABLE;
d->block_types[BURN_WRITE_SAO] = 0; d->block_types[BURN_WRITE_SAO] = 0;
if (stbuf.st_size / (off_t) 2048 if (stbuf.st_size > BURN_DRIVE_MAX_BYTES) {
>= 0x7ffffff0) {
d->status = BURN_DISC_FULL; d->status = BURN_DISC_FULL;
d->role_5_nwa = 0x7ffffff0; d->role_5_nwa =
(off_t) BURN_DRIVE_MAX_BYTES /
(off_t) 2048; ;
} else } else
d->role_5_nwa = stbuf.st_size / 2048 + d->role_5_nwa = stbuf.st_size / 2048 +
!!(stbuf.st_size % 2048); !!(stbuf.st_size % 2048);
@ -1915,7 +1987,7 @@ int burn_drive_scan_and_grab(struct burn_drive_info *drive_infos[], char* adr,
unsigned int n_drives; unsigned int n_drives;
int ret, i; int ret, i;
/* check wether drive address is already registered */ /* check whether drive address is already registered */
for (i = 0; i <= drivetop; i++) for (i = 0; i <= drivetop; i++)
if (drive_array[i].global_index >= 0) if (drive_array[i].global_index >= 0)
if (strcmp(drive_array[i].devname, adr) == 0) if (strcmp(drive_array[i].devname, adr) == 0)
@ -2020,7 +2092,7 @@ int burn_drive_get_adr(struct burn_drive_info *drive_info, char adr[])
/* ts A60922 ticket 33 */ /* ts A60922 ticket 33 */
/** Evaluate wether the given address would be enumerated by libburn */ /** Evaluate whether the given address would be enumerated by libburn */
int burn_drive_is_enumerable_adr(char *adr) int burn_drive_is_enumerable_adr(char *adr)
{ {
return sg_is_enumerable_adr(adr); return sg_is_enumerable_adr(adr);
@ -2254,12 +2326,12 @@ int burn_drive_find_scsi_equiv(char *path, char adr[])
burn_drive_adr_debug_msg(msg, NULL); burn_drive_adr_debug_msg(msg, NULL);
return 0; return 0;
} }
sprintf(msg, "burn_drive_find_scsi_equiv( %s ) : (%d),%d,%d,%d,%d", sprintf(msg, "burn_drive_find_scsi_equiv( %s ) : %d,%d,%d,%d,%d",
path, bus_no, host_no, channel_no, target_no, lun_no); path, bus_no, host_no, channel_no, target_no, lun_no);
burn_drive_adr_debug_msg(msg, NULL); burn_drive_adr_debug_msg(msg, NULL);
ret= burn_drive_convert_scsi_adr(-1, host_no, channel_no, target_no, ret= burn_drive_convert_scsi_adr(bus_no, host_no, channel_no,
lun_no, adr); target_no, lun_no, adr);
return ret; return ret;
} }
@ -2621,10 +2693,10 @@ int burn_disc_read_atip(struct burn_drive *d)
} }
/* ts A61110 : new API function */ /* ts A61110 : new API function */
int burn_disc_track_lba_nwa(struct burn_drive *d, struct burn_write_opts *o, int burn_disc_track_lba_nwa_v2(struct burn_drive *d, struct burn_write_opts *o,
int trackno, int *lba, int *nwa) int trackno, off_t *lba, off_t *nwa)
{ {
int ret; int ret, int_lba, int_nwa;
if (burn_drive_is_released(d)) { if (burn_drive_is_released(d)) {
libdax_msgs_submit(libdax_messenger, libdax_msgs_submit(libdax_messenger,
@ -2652,11 +2724,38 @@ int burn_disc_track_lba_nwa(struct burn_drive *d, struct burn_write_opts *o,
return 0; return 0;
if (o != NULL) if (o != NULL)
d->send_write_parameters(d, NULL, -1, o); d->send_write_parameters(d, NULL, -1, o);
ret = d->get_nwa(d, trackno, lba, nwa); ret = d->get_nwa(d, trackno, &int_lba, &int_nwa);
if (ret <= 0)
return ret;
*lba = int_lba;
*nwa = int_nwa;
return ret; return ret;
} }
/* ts A61110 / C40302 : API */
int burn_disc_track_lba_nwa(struct burn_drive *d, struct burn_write_opts *o,
int trackno, int *lba, int *nwa)
{
int ret;
off_t off_lba, off_nwa;
ret = burn_disc_track_lba_nwa_v2(d, o, trackno, &off_lba, &off_nwa);
if (ret <= 0)
return ret;
if (off_lba > 0x7fffffff)
*lba = 0x7fffffff;
else
*lba = off_lba;
if (off_nwa > 0x7fffffff) {
*nwa = 0x7fffffff;
return 0;
} else {
*nwa = off_nwa;
}
return 1;
}
/* ts A70131 : new API function */ /* ts A70131 : new API function */
int burn_disc_get_msc1(struct burn_drive *d, int *start) int burn_disc_get_msc1(struct burn_drive *d, int *start)
{ {
@ -2706,7 +2805,7 @@ off_t burn_disc_available_space(struct burn_drive *d,
if (ret != 1) if (ret != 1)
bytes = d->media_capacity_remaining; bytes = d->media_capacity_remaining;
if (bytes <= 0) if (bytes <= 0)
bytes = (off_t) (512 * 1024 * 1024 - 1) * (off_t) 2048; bytes = BURN_DRIVE_MAX_BYTES;
if (bytes != d->media_capacity_remaining) if (bytes != d->media_capacity_remaining)
burn_drive_set_media_capacity_remaining(d, bytes); burn_drive_set_media_capacity_remaining(d, bytes);
} else { } else {
@ -3049,7 +3148,7 @@ int burn_disc_get_multi_caps(struct burn_drive *d, enum burn_write_types wt,
d->current_profile == 0x1a || d->current_profile == 0x1a ||
d->current_profile == 0x43 d->current_profile == 0x43
) { ) {
/* DVD-RAM, overwriteable DVD-RW, DVD+RW, BD-RE */ /* DVD-RAM, overwritable DVD-RW, DVD+RW, BD-RE */
o->start_adr = 1; o->start_adr = 1;
ret = burn_disc_get_formats(d, &status, &size, &dummy, ret = burn_disc_get_formats(d, &status, &size, &dummy,
&num_formats); &num_formats);
@ -3308,7 +3407,7 @@ int burn_drive_equals_adr(struct burn_drive *d1, char *adr2_in, int role2)
/* one dir existing, one not */ /* one dir existing, one not */
/* Both directories exist. The basenames are equal. /* Both directories exist. The basenames are equal.
So the adresses are equal if the directories are So the addresses are equal if the directories are
equal.*/ equal.*/
} }
if (stbuf1.st_ino == stbuf2.st_ino && if (stbuf1.st_ino == stbuf2.st_ino &&
@ -3389,21 +3488,38 @@ int burn_drive_find_by_thread_pid(struct burn_drive **d, pid_t pid,
*/ */
int burn_drive_set_media_capacity_remaining(struct burn_drive *d, off_t value) int burn_drive_set_media_capacity_remaining(struct burn_drive *d, off_t value)
{ {
if (value / (off_t) 2048 > (off_t) 0x7ffffff0) if (value > BURN_DRIVE_MAX_BYTES)
value = ((off_t) 0x7ffffff0) * (off_t) 2048; value = BURN_DRIVE_MAX_BYTES;
d->media_capacity_remaining = value; d->media_capacity_remaining = value;
return 1; return 1;
} }
/* ts C40303 : API */
int burn_get_read_capacity_v2(struct burn_drive *d, off_t *capacity, int flag)
{
*capacity = d->media_read_capacity +
(d->media_read_capacity != 0x7fffffffffffffff);
return (d->media_read_capacity != 0x7fffffffffffffff);
}
/* ts A81215 : API */ /* ts A81215 : API */
int burn_get_read_capacity(struct burn_drive *d, int *capacity, int flag) int burn_get_read_capacity(struct burn_drive *d, int *capacity, int flag)
{ {
*capacity = d->media_read_capacity + int ret;
(d->media_read_capacity != 0x7fffffff); off_t cap;
return (d->media_read_capacity != 0x7fffffff);
}
ret= burn_get_read_capacity_v2(d, &cap, flag);
if (cap < -0x7fffffff) {
*capacity = -0x7fffffff;
ret = 0;
} else if (cap > 0x7fffffff) {
*capacity = 0x7fffffff;
ret = 0;
} else {
*capacity = cap;
}
return ret;
}
/* ts A90903 : API */ /* ts A90903 : API */
int burn_disc_get_media_id(struct burn_drive *d, int burn_disc_get_media_id(struct burn_drive *d,
@ -3432,7 +3548,7 @@ int burn_disc_get_media_id(struct burn_drive *d,
bit3= disc_app_code valid bit3= disc_app_code valid
bit4= Disc is unrestricted (URU bit) bit4= Disc is unrestricted (URU bit)
bit5= Disc is nominally erasable (Erasable bit) bit5= Disc is nominally erasable (Erasable bit)
This will be set with overwriteable media which This will be set with overwritable media which
libburn normally considers to be unerasable blank. libburn normally considers to be unerasable blank.
*/ */
int burn_disc_get_cd_info(struct burn_drive *d, char disc_type[80], int burn_disc_get_cd_info(struct burn_drive *d, char disc_type[80],

View File

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2014 Thomas Schmitt <scdbackup@gmx.net> Copyright (c) 2006 - 2024 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later. Provided under GPL version 2 or later.
*/ */
@ -170,4 +170,12 @@ int burn_drive_has_feature(struct burn_drive *d, int feature_code,
int burn_drive_grab_stdio(struct burn_drive *d, int flag); int burn_drive_grab_stdio(struct burn_drive *d, int flag);
/* ts C10213 */
/* The size of limitless or oversized devices as pseudo drives */
/* Do not lightheartedly change this value because of its meaning to
burn_drive.media_read_capacity in libburn/transport.h
64 TiB = 2 exp 46 = 2 exp 35 blocks
*/
#define BURN_DRIVE_MAX_BYTES ((off_t) (0x800000000) * (off_t) 2048)
#endif /* __DRIVE */ #endif /* __DRIVE */

View File

@ -75,11 +75,11 @@
>>> See correctness reservation below. >>> See correctness reservation below.
Algebra on Galois fields is the same as on Rational Numbers. Algebra on Galois fields is the same as on Rational Numbers.
But arithmetics is defined by operations on polynomials rather than the But arithmetics on its polynomials differ from usual integer arithmetics
usual integer arithmetics on binary numbers. on binary numbers.
Addition and subtraction are identical with the binary exor operator. Addition and subtraction are identical with the binary exor operator.
Multiplication and division would demand polynomial division, e.g. by the Multiplication and division would demand polynomial division, e.g. by the
euclidian algorithm. The computing path over logarithms and powers follows euclidean algorithm. The computing path over logarithms and powers follows
algebra and reduces the arithmetic task to table lookups, additions algebra and reduces the arithmetic task to table lookups, additions
modulo 255, and exor operations. Note that the logarithms are natural modulo 255, and exor operations. Note that the logarithms are natural
numbers, not polynomials. They get added or subtracted by the usual addition numbers, not polynomials. They get added or subtracted by the usual addition

View File

@ -43,7 +43,7 @@ an unreadable disc */
/* This is a generic OS oriented function wrapper which compensates /* This is a generic OS oriented function wrapper which compensates
shortcommings of read() in respect to a guaranteed amount of return data. shortcomings of read() in respect to a guaranteed amount of return data.
See man 2 read , paragraph "RETURN VALUE". See man 2 read , paragraph "RETURN VALUE".
*/ */
static int read_full_buffer(int fd, unsigned char *buffer, int size) static int read_full_buffer(int fd, unsigned char *buffer, int size)

View File

@ -88,7 +88,7 @@ struct burn_source_offst {
int size_adjustable; int size_adjustable;
/* for set_size/get_size */ /* for set_size/get_size */
int nominal_size; off_t nominal_size;
/* To help offst_free() */ /* To help offst_free() */
struct burn_source *next; struct burn_source *next;

View File

@ -52,7 +52,7 @@ double lib_start_time;
*/ */
int burn_sg_open_o_excl = 1; int burn_sg_open_o_excl = 1;
/* ts A70403 : GNU/Linux: wether to use fcntl(,F_SETLK,) /* ts A70403 : GNU/Linux: whether to use fcntl(,F_SETLK,)
after open() of device files */ after open() of device files */
int burn_sg_fcntl_f_setlk = 1; int burn_sg_fcntl_f_setlk = 1;
@ -71,7 +71,7 @@ int burn_sg_use_family = 0;
has been thoroughly tested. */ has been thoroughly tested. */
int burn_sg_open_o_nonblock = 1; int burn_sg_open_o_nonblock = 1;
/* wether to take a busy drive as an error */ /* whether to take a busy drive as an error */
/* Caution: this is implemented by a rough hack and eventually leads /* Caution: this is implemented by a rough hack and eventually leads
to unconditional abort of the process */ to unconditional abort of the process */
int burn_sg_open_abort_busy = 0; int burn_sg_open_abort_busy = 0;
@ -98,7 +98,7 @@ int burn_builtin_signal_action = 0; /* burn_set_signal_handling() */
volatile int burn_builtin_triggered_action = 0; /* burn_is_aborting() */ volatile int burn_builtin_triggered_action = 0; /* burn_is_aborting() */
/* ts A70223 : wether implemented untested profiles are supported */ /* ts A70223 : whether implemented untested profiles are supported */
int burn_support_untested_profiles = 0; int burn_support_untested_profiles = 0;
/* ts A91111 : /* ts A91111 :
@ -112,7 +112,7 @@ int burn_sg_log_scsi = 0;
/* ts B10312 : /* ts B10312 :
Whether to map random-access readonly files to drive role 4. Whether to map random-access readonly files to drive role 4.
Else it is role 2 overwriteable drive Else it is role 2 overwritable drive
*/ */
int burn_drive_role_4_allowed = 0; int burn_drive_role_4_allowed = 0;

View File

@ -12,7 +12,7 @@ extern int burn_running;
extern double lib_start_time; extern double lib_start_time;
/** Indicator for burn_drive_get_status() wether a signal hit parts of the /** Indicator for burn_drive_get_status() whether a signal hit parts of the
thread team. thread team.
0= all works well , 0= all works well ,
1 to 5 = waiting for eventual signal on control thread 1 to 5 = waiting for eventual signal on control thread

View File

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2019 Thomas Schmitt <scdbackup@gmx.net> Copyright (c) 2006 - 2024 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later. Provided under GPL version 2 or later.
This is the official API definition of libburn. This is the official API definition of libburn.
@ -9,6 +9,8 @@
*/ */
/* Important: If you add a public API function then add its name to file /* Important: If you add a public API function then add its name to file
libburn/libburn.ver libburn/libburn.ver
in the node LIBBURN4_Major.Minor.Micro with the numbers of
the next release version, citing the previous node.
*/ */
@ -29,6 +31,9 @@ processing tracks of more than 2 GB size.
*/ */
#include <sys/types.h> #include <sys/types.h>
/* For struct timeval */
#include <sys/time.h>
#ifndef DOXYGEN #ifndef DOXYGEN
#if defined(__cplusplus) #if defined(__cplusplus)
@ -144,7 +149,7 @@ enum burn_write_types
With sequential DVD-R[W]: Incremental Streaming With sequential DVD-R[W]: Incremental Streaming
With DVD+R and BD-R: Track of open size With DVD+R and BD-R: Track of open size
With DVD-RAM, DVD+RW, BD-RE: Random Writeable (used sequentially) With DVD-RAM, DVD+RW, BD-RE: Random Writeable (used sequentially)
With overwriteable DVD-RW: Rigid Restricted Overwrite With overwritable DVD-RW: Rigid Restricted Overwrite
*/ */
BURN_WRITE_TAO, BURN_WRITE_TAO,
@ -235,7 +240,7 @@ enum burn_disc_status
CD-R, CD-RW, DVD-R, DVD-RW, DVD+R, BD-R CD-R, CD-RW, DVD-R, DVD-RW, DVD+R, BD-R
Blanked multi-session media (i.e. treated by burn_disc_erase()) Blanked multi-session media (i.e. treated by burn_disc_erase())
CD-RW, DVD-RW CD-RW, DVD-RW
Overwriteable media with or without valid data Overwritable media with or without valid data
DVD-RAM, DVD+RW, formatted DVD-RW, BD-RE DVD-RAM, DVD+RW, formatted DVD-RW, BD-RE
*/ */
BURN_DISC_BLANK, BURN_DISC_BLANK,
@ -373,6 +378,9 @@ struct burn_toc_entry
@since 0.5.2 : DVD extensions are made valid for CD too @since 0.5.2 : DVD extensions are made valid for CD too
bit1= LRA extension is valid @since 0.7.2 bit1= LRA extension is valid @since 0.7.2
bit2= Track status bits extension is valid @since 1.2.8 bit2= Track status bits extension is valid @since 1.2.8
bit3= Long block address is valid:
long_start_lba, long_track_blocks, long_last_rec_adr
@since 1.5.8
*/ */
unsigned char extensions_valid; unsigned char extensions_valid;
@ -383,8 +391,10 @@ struct burn_toc_entry
unsigned char session_msb; unsigned char session_msb;
unsigned char point_msb; unsigned char point_msb;
/* pmin, psec, and pframe may be too small if DVD extension is valid */ /* pmin, psec, and pframe may be too small if DVD extension is valid */
/* -1 means that only long_start_lba is valid */
int start_lba; int start_lba;
/* min, sec, and frame may be too small if DVD extension is valid */ /* min, sec, and frame may be too small if DVD extension is valid */
/* -1 means that only long_track_blocks is valid */
int track_blocks; int track_blocks;
/* ts A90909 : LRA extension. extensions_valid:bit1 */ /* ts A90909 : LRA extension. extensions_valid:bit1 */
@ -393,6 +403,7 @@ struct burn_toc_entry
DVD-R DL when LJRS = 00b, DVD-RW, HD DVD-R, and BD-R. DVD-R DL when LJRS = 00b, DVD-RW, HD DVD-R, and BD-R.
This would mean profiles: 0x11, 0x15, 0x13, 0x14, 0x51, 0x41, 0x42 This would mean profiles: 0x11, 0x15, 0x13, 0x14, 0x51, 0x41, 0x42
*/ */
/* -1 means that only long_last_rec_adr is valid */
int last_recorded_address; int last_recorded_address;
/* ts B30112 : Track status bits extension. extensions_valid:bit2 */ /* ts B30112 : Track status bits extension. extensions_valid:bit2 */
@ -412,6 +423,12 @@ struct burn_toc_entry
*/ */
int track_status_bits; int track_status_bits;
/* ts C40221 : Long block address extension. extensions_valid:bit3 */
/* @since 1.5.8 */
off_t long_start_lba;
off_t long_track_blocks;
off_t long_last_rec_adr;
}; };
@ -663,7 +680,8 @@ struct burn_drive_info
/** Operation progress report. All values are 0 based indices. /** Operation progress report. All values are 0 based indices.
* */ Handed out by burn_drive_get_status().
**/
struct burn_progress { struct burn_progress {
/** The total number of sessions */ /** The total number of sessions */
int sessions; int sessions;
@ -675,7 +693,7 @@ struct burn_progress {
int track; int track;
/** The total number of indices */ /** The total number of indices */
int indices; int indices;
/** Curent index. */ /** Current index. */
int index; int index;
/** The starting logical block address */ /** The starting logical block address */
int start_sector; int start_sector;
@ -705,6 +723,52 @@ struct burn_progress {
}; };
/** Operation progress report with long block numbers.
All values are 0 based indices.
Handed out by burn_drive_get_status_v2().
@since 1.5.8
**/
struct burn_progress_v2 {
/** Revision of the struct format.
0= Elements up to .buffer_min_fill */
int revision;
/** The total number of sessions */
int sessions;
/** Current session.*/
int session;
/** The total number of tracks */
int tracks;
/** Current track. */
int track;
/** The total number of indices */
int indices;
/** Current index. */
int index;
/** The starting logical block address */
off_t start_sector;
/** On write: The number of sectors.
On blank: 0x10000 as upper limit for relative progress steps */
off_t sectors;
/** On write: The current sector being processed.
On blank: Relative progress steps 0 to 0x10000 */
off_t sector;
/** The capacity of the drive buffer */
off_t buffer_capacity;
/** The free space in the drive buffer (might be slightly outdated) */
off_t buffer_available;
/** The number of bytes sent to the drive buffer */
off_t buffered_bytes;
/** The minimum number of bytes stored in buffer during write.
(Caution: Before surely one buffer size of bytes was processed,
this value is 0x7fffffffffffffff.)
*/
off_t buffer_min_fill;
};
/* ts A61226 */ /* ts A61226 */
/* @since 0.3.0 */ /* @since 0.3.0 */
/** Description of a speed capability as reported by the drive in conjunction /** Description of a speed capability as reported by the drive in conjunction
@ -1328,7 +1392,7 @@ int burn_drive_get_bd_r_pow(struct burn_drive *drive);
/* ts A61020 */ /* ts A61020 */
/** Returns start and end lba of the media which is currently inserted /** Returns start and end lba of the media which is currently inserted
in the given drive. The drive has to be grabbed to have hope for reply. in the given drive. The drive has to be grabbed to have hope for reply.
Shortcomming (not a feature): unless burn_disc_read_atip() was called Shortcoming (not a feature): unless burn_disc_read_atip() was called
only blank media will return valid info. only blank media will return valid info.
@param drive The drive to query. @param drive The drive to query.
@param start_lba Returns the start lba value @param start_lba Returns the start lba value
@ -1386,7 +1450,7 @@ char *burn_guess_cd_manufacturer(int m_li, int s_li, int f_li,
This seems to be broken with my drives. The bit is This seems to be broken with my drives. The bit is
0 and the validity bit for disc_app_code is 0 too. 0 and the validity bit for disc_app_code is 0 too.
bit5= Disc is nominally erasable (Erasable bit) bit5= Disc is nominally erasable (Erasable bit)
This will be set with overwriteable media which This will be set with overwritable media which
libburn normally considers to be unerasable blank. libburn normally considers to be unerasable blank.
@return 1 success, <= 0 an error occurred @return 1 success, <= 0 an error occurred
@since 0.7.2 @since 0.7.2
@ -1478,6 +1542,13 @@ int burn_disc_get_phys_format_info(struct burn_drive *d, int *disk_category,
int burn_disc_track_lba_nwa(struct burn_drive *d, struct burn_write_opts *o, int burn_disc_track_lba_nwa(struct burn_drive *d, struct burn_write_opts *o,
int trackno, int *lba, int *nwa); int trackno, int *lba, int *nwa);
/* ts C40302 */
/** Like burn_disc_track_lba_nwa(), but with off_t results.
@since 1.5.8
*/
int burn_disc_track_lba_nwa_v2(struct burn_drive *d, struct burn_write_opts *o,
int trackno, off_t *lba, off_t *nwa);
/* ts B10525 */ /* ts B10525 */
/** Tells whether a previous attempt to determine the Next Writeable Address /** Tells whether a previous attempt to determine the Next Writeable Address
of the upcoming track reveiled that the READ TRACK INFORMATION Damage Bit of the upcoming track reveiled that the READ TRACK INFORMATION Damage Bit
@ -1650,6 +1721,15 @@ int burn_disc_erasable(struct burn_drive *d);
enum burn_drive_status burn_drive_get_status(struct burn_drive *drive, enum burn_drive_status burn_drive_get_status(struct burn_drive *drive,
struct burn_progress *p); struct burn_progress *p);
/** Returns the progress with long block numbers and the status of the drive.
@param drive The drive to query busy state for.
@param p Returns the progress of the operation, NULL if you don't care
@return the current status of the drive. See also burn_drive_status.
@since 1.5.8
*/
enum burn_drive_status burn_drive_get_status_v2(struct burn_drive *drive,
struct burn_progress_v2 *p);
/** Creates a write_opts struct for burning to the specified drive. /** Creates a write_opts struct for burning to the specified drive.
The returned object must later be freed with burn_write_opts_free(). The returned object must later be freed with burn_write_opts_free().
@param drive The drive to write with @param drive The drive to write with
@ -1819,7 +1899,7 @@ void burn_disc_read(struct burn_drive *drive, const struct burn_read_opts *o);
with drive and media. This function is called by burn_disc_write() but with drive and media. This function is called by burn_disc_write() but
an application might be interested in this check in advance. an application might be interested in this check in advance.
@param o The options for the writing operation. @param o The options for the writing operation.
@param disc The descrition of the disc to be created @param disc The description of the disc to be created
@param reasons Eventually returns a list of rejection reason statements @param reasons Eventually returns a list of rejection reason statements
@param silent 1= do not issue error messages , 0= report problems @param silent 1= do not issue error messages , 0= report problems
@return 1 ok, -1= no recordable media detected, 0= other failure @return 1 ok, -1= no recordable media detected, 0= other failure
@ -2983,6 +3063,11 @@ int burn_track_set_size(struct burn_track *t, off_t size);
*/ */
int burn_track_get_sectors(struct burn_track *); int burn_track_get_sectors(struct burn_track *);
/* ts C40302 */
/** Like burn_track_get_sectors(), but with return type off_t.
@since 1.5.8
*/
off_t burn_track_get_sectors_v2(struct burn_track *);
/* ts A61101 */ /* ts A61101 */
/** Tells how many source bytes have been read and how many data bytes have /** Tells how many source bytes have been read and how many data bytes have
@ -2996,7 +3081,7 @@ int burn_track_get_counters(struct burn_track *t,
off_t *read_bytes, off_t *written_bytes); off_t *read_bytes, off_t *written_bytes);
/** Sets drive read and write speed /** Sets drive read and write speed.
Note: "k" is 1000, not 1024. Note: "k" is 1000, not 1024.
1xCD = 176.4 k/s, 1xDVD = 1385 k/s, 1xBD = 4496 k/s. 1xCD = 176.4 k/s, 1xDVD = 1385 k/s, 1xBD = 4496 k/s.
Fractional speeds should be rounded up. Like 4xCD = 706. Fractional speeds should be rounded up. Like 4xCD = 706.
@ -3007,6 +3092,63 @@ int burn_track_get_counters(struct burn_track *t,
void burn_drive_set_speed(struct burn_drive *d, int read, int write); void burn_drive_set_speed(struct burn_drive *d, int read, int write);
/* ts C00822 */
/** Sets drive read and write speed using the "Exact" bit of SCSI command
SET STREAMING. This command will be used even if a CD medium is present.
MMC specifies that with the Exact bit the desired speed settings shall
either be obeyed by the drive exactly, or that the drive shall indicate
failure and not accept the settings.
But many drives reply no error and nevertheless adjust their read speed
only coarsly or ignore the setting after a few MB of fast read attempts.
The call parameters have the same meaning as with burn_drive_set_speed().
@param d The drive to set speed for. It must be a role 1 drive.
@param read Read speed in k/s (0 is max, -1 is min).
@param write Write speed in k/s (0 is max, -1 is min).
@return 1=success , 0=failure
@since 1.5.4
*/
int burn_drive_set_speed_exact(struct burn_drive *d, int read, int write);
/* ts C00822 */
/** Waits until the time has elapsed since the given previous time to transmit
the given byte count with the given speed in KB/second (KB = 1000 bytes).
This call may be used between random access read operations like
burn_read_data() in order to force a slower speed than the drive is
willing to use if it gets read requests as fast as it delivers data.
The parameter us_corr carries microseconds of time deviations from one
call to the next one. Such deviations may happen because of small
inexactnesses of the sleeper function and because of temporary delays
in the data supply so that sleeping for a negative time span would have
been necessary. The next call will reduce or enlarge its own sleeping
period by this value.
@param kb_per_second the desired speed in 1000 bytes per second.
Supplied by the caller.
@max_corr the maximum backlog in microseconds which shall
be compensated by the next call. Supplied by the
caller. Not more than 1 billion = 1000 seconds.
@param prev_time time keeper updated by burn_nominal_slowdown().
The caller provides the memory and elsewise should
carry it unchanged from call to call.
@param us_corr updated by burn_nominal_slowdown(). See above.
The caller provides the memory and elsewise should
carry it unchanged from call to call.
@param b_since_prev byte count since the previous call. This number
has to be counted and supplied by the caller.
@param flag Bitfield for control purposes:
bit0= initialize *prev_time and *us_corr,
ignore other parameters, do not wait
@return 2=no wait because no usable kb_per_second , 1=success , 0=failure
@since 1.5.4
*/
int burn_nominal_slowdown(int kb_per_second, int max_corr,
struct timeval *prev_time,
int *us_corr, off_t b_since_prev, int flag);
/* ts A70711 */ /* ts A70711 */
/** Controls the behavior with writing when the drive buffer is suspected to /** Controls the behavior with writing when the drive buffer is suspected to
be full. To check and wait for enough free buffer space before writing be full. To check and wait for enough free buffer space before writing
@ -3277,9 +3419,13 @@ void burn_write_opts_set_fillup(struct burn_write_opts *opts,
/* ts A70303 */ /* ts A70303 */
/** Eventually makes libburn ignore the failure of some conformance checks: /** Lets libburn ignore the failure of some conformance checks:
- the check whether CD write+block type is supported by the drive - the check whether CD write+block type is supported by the drive
- the check whether the media profile supports simulated burning - the check whether the media profile supports simulated burning
- @since 1.5.6
The check whether a write operation exceeds the size of the medium
as announced by the drive. This is known as "overburn" and may work
for a few thousand additional blocks on CD media with write type SAO.
@param opts The write opts to change @param opts The write opts to change
@param use_force 1=ignore above checks, 0=refuse work on failed check @param use_force 1=ignore above checks, 0=refuse work on failed check
@since 0.3.4 @since 0.3.4
@ -3329,12 +3475,27 @@ void burn_write_opts_set_dvd_obs(struct burn_write_opts *opts, int obs);
void burn_write_opts_set_obs_pad(struct burn_write_opts *opts, int pad); void burn_write_opts_set_obs_pad(struct burn_write_opts *opts, int pad);
/* ts C10909 */
/** Exempts BD-R media from the elsewise unavoidable automatic padding of the
last write chunk to its full size.
Even if this exempt is granted it gets into effect only if stream recording
is disabled and burn_write_opts_set_obs_pad() is set to 0.
@param opts The write opts to change
@param value 1= possibly exempt BD-R from end chunk padding.
0= always act on BD-R as if
burn_write_opts_set_obs_pad(opts, 1) is in effect.
@since 1.5.6
*/
void burn_write_opts_set_bdr_obs_exempt(struct burn_write_opts *opts,
int value);
/* ts A91115 */ /* ts A91115 */
/** Sets the rhythm by which stdio pseudo drives force their output data to /** Sets the rhythm by which stdio pseudo drives force their output data to
be consumed by the receiving storage device. This forcing keeps the memory be consumed by the receiving storage device. This forcing keeps the memory
from being clogged with lots of pending data for slow devices. from being clogged with lots of pending data for slow devices.
@param opts The write opts to change @param opts The write opts to change
@param rythm Number of 2KB output blocks after which fsync(2) is @param rhythm Number of 2KB output blocks after which fsync(2) is
performed. performed.
-1 means no fsync() -1 means no fsync()
0 means default 0 means default
@ -3343,7 +3504,7 @@ void burn_write_opts_set_obs_pad(struct burn_write_opts *opts, int pad);
Default is currently 8192 = 16 MB. Default is currently 8192 = 16 MB.
@since 0.7.4 @since 0.7.4
*/ */
void burn_write_opts_set_stdio_fsync(struct burn_write_opts *opts, int rythm); void burn_write_opts_set_stdio_fsync(struct burn_write_opts *opts, int rhythm);
/** Sets whether to read in raw mode or not /** Sets whether to read in raw mode or not
@ -3628,12 +3789,12 @@ struct burn_multi_caps {
/** Profile number which was current when the reply was generated */ /** Profile number which was current when the reply was generated */
int current_profile; int current_profile;
/** Wether the current profile indicates CD media. 1=yes, 0=no */ /** Whether the current profile indicates CD media. 1=yes, 0=no */
int current_is_cd_profile; int current_is_cd_profile;
/* ts A70528 */ /* ts A70528 */
/* @since 0.3.8 */ /* @since 0.3.8 */
/** Wether the current profile is able to perform simulated write */ /** Whether the current profile is able to perform simulated write */
int might_simulate; int might_simulate;
}; };
@ -3700,8 +3861,19 @@ struct burn_session **burn_disc_get_sessions(struct burn_disc *d,
int burn_disc_get_incomplete_sessions(struct burn_disc *d); int burn_disc_get_incomplete_sessions(struct burn_disc *d);
/** Tells how many sectors a disc will have, or already has.
This is the sum of all burn_session_get_sectors() results of the disc.
The result is NOT RELIABLE with tracks of undefined length
*/
int burn_disc_get_sectors(struct burn_disc *d); int burn_disc_get_sectors(struct burn_disc *d);
/* ts C40302 */
/** Like burn_disc_get_sectors(), but with return type off_t.
@since 1.5.8
*/
off_t burn_disc_get_sectors_v2(struct burn_disc *d);
/** Gets an array of all the tracks for a session /** Gets an array of all the tracks for a session
THIS IS NO LONGER VALID AFTER YOU ADD OR REMOVE A TRACK THIS IS NO LONGER VALID AFTER YOU ADD OR REMOVE A TRACK
@param s session to get track array for @param s session to get track array for
@ -3711,8 +3883,19 @@ int burn_disc_get_sectors(struct burn_disc *d);
struct burn_track **burn_session_get_tracks(struct burn_session *s, struct burn_track **burn_session_get_tracks(struct burn_session *s,
int *num); int *num);
/** Tells how many sectors a session will have, or already has on disc.
This is the sum of all burn_track_get_sectors() results of the session.
The result is NOT RELIABLE with tracks of undefined length
*/
int burn_session_get_sectors(struct burn_session *s); int burn_session_get_sectors(struct burn_session *s);
/* ts C40302 */
/** Like burn_session_get_sectors(), but with return type off_t.
@since 1.5.8
*/
off_t burn_session_get_sectors_v2(struct burn_session *s);
/** Gets the mode of a track /** Gets the mode of a track
@param track the track to query @param track the track to query
@return the track's mode @return the track's mode
@ -3755,7 +3938,7 @@ void burn_version(int *major, int *minor, int *micro);
*/ */
#define burn_header_version_major 1 #define burn_header_version_major 1
#define burn_header_version_minor 5 #define burn_header_version_minor 5
#define burn_header_version_micro 2 #define burn_header_version_micro 7
/** Note: /** Note:
Above version numbers are also recorded in configure.ac because libtool Above version numbers are also recorded in configure.ac because libtool
wants them as parameters at build time. wants them as parameters at build time.
@ -3765,7 +3948,7 @@ void burn_version(int *major, int *minor, int *micro);
/** Usage discussion: /** Usage discussion:
Some developers of the libburnia project have differing Some developers of the libburnia project have differing
opinions how to ensure the compatibility of libaries opinions how to ensure the compatibility of libraries
and applications. and applications.
It is about whether to use at compile time and at runtime It is about whether to use at compile time and at runtime
@ -4015,7 +4198,7 @@ int burn_is_aborting(int flag);
/** Write data in random access mode. /** Write data in random access mode.
The drive must be grabbed successfully before calling this function which The drive must be grabbed successfully before calling this function which
circumvents usual libburn session processing and rather writes data without circumvents usual libburn session processing and rather writes data without
preparations or finalizing. This will work only with overwriteable media preparations or finalizing. This will work only with overwritable media
which are also suitable for burn_write_opts_set_start_byte(). The same which are also suitable for burn_write_opts_set_start_byte(). The same
address alignment restrictions as with this function apply. I.e. for DVD address alignment restrictions as with this function apply. I.e. for DVD
it is best to align to 32 KiB blocks (= 16 LBA units). The amount of data it is best to align to 32 KiB blocks (= 16 LBA units). The amount of data
@ -4051,10 +4234,13 @@ int burn_random_access_write(struct burn_drive *d, off_t byte_address,
/* ts A81215 */ /* ts A81215 */
/** Inquire the maximum amount of readable data. /** Inquire the maximum amount of readable data.
It is supposed that all LBAs in the range from 0 to capacity - 1 On DVD and BD it is supposed that all LBAs in the range from 0 to
can be read via burn_read_data() although some of them may never have been capacity - 1 can be read via burn_read_data() although some of them may
recorded. If tracks are recognizable then it is better to only read never have been recorded. With multi-session CD there have to be
LBAs which are part of some track. expected unreadable TAO Run-out blocks.
If tracks are recognizable then it is better to only read LBAs which
are part of some track and on CD to be cautious about the last two blocks
of each track which might be TAO Run-out blocks.
If the drive is actually a large file or block device, then the capacity If the drive is actually a large file or block device, then the capacity
is curbed to a maximum of 0x7ffffff0 blocks = 4 TB - 32 KB. is curbed to a maximum of 0x7ffffff0 blocks = 4 TB - 32 KB.
@param d The drive from which to read @param d The drive from which to read
@ -4065,6 +4251,12 @@ int burn_random_access_write(struct burn_drive *d, off_t byte_address,
*/ */
int burn_get_read_capacity(struct burn_drive *d, int *capacity, int flag); int burn_get_read_capacity(struct burn_drive *d, int *capacity, int flag);
/* ts C40303 */
/** Like burn_get_read_capacity(), but with off_t result.
@since 1.5.8
*/
int burn_get_read_capacity_v2(struct burn_drive *d, off_t *capacity, int flag);
/* ts A70812 */ /* ts A70812 */
/** Read data in random access mode. /** Read data in random access mode.
@ -4295,7 +4487,7 @@ int burn_drive_equals_adr(struct burn_drive *d1, char *adr2, int drive_role2);
struct libdax_audioxtr; struct libdax_audioxtr;
/** Open an audio file, check wether suitable, create extractor object. /** Open an audio file, check whether suitable, create extractor object.
@param xtr Opaque handle to extractor. Gets attached extractor object. @param xtr Opaque handle to extractor. Gets attached extractor object.
@param path Address of the audio file to extract. "-" is stdin (but might @param path Address of the audio file to extract. "-" is stdin (but might
be not suitable for all futurely supported formats). be not suitable for all futurely supported formats).
@ -4393,7 +4585,7 @@ BURN_END_DECLS
/* The following experiments may be interesting in future: /* The following experiments may be interesting in future:
*/ */
/* Perform OPC explicitely. /* Perform OPC explicitly.
# define Libburn_pioneer_dvr_216d_with_opC 1 # define Libburn_pioneer_dvr_216d_with_opC 1
*/ */

View File

@ -80,6 +80,7 @@ burn_drive_scan_and_grab;
burn_drive_set_buffer_waiting; burn_drive_set_buffer_waiting;
burn_drive_set_immed; burn_drive_set_immed;
burn_drive_set_speed; burn_drive_set_speed;
burn_drive_set_speed_exact;
burn_drive_set_stream_recording; burn_drive_set_stream_recording;
burn_drive_snooze; burn_drive_snooze;
burn_drive_was_feat21_failure; burn_drive_was_feat21_failure;
@ -107,6 +108,7 @@ burn_msf_to_sectors;
burn_msgs_obtain; burn_msgs_obtain;
burn_msgs_set_severities; burn_msgs_set_severities;
burn_msgs_submit; burn_msgs_submit;
burn_nominal_slowdown;
burn_obtain_profile_name; burn_obtain_profile_name;
burn_offst_source_new; burn_offst_source_new;
burn_os_alloc_buffer; burn_os_alloc_buffer;
@ -184,6 +186,7 @@ burn_write_opts_auto_write_type;
burn_write_opts_free; burn_write_opts_free;
burn_write_opts_get_drive; burn_write_opts_get_drive;
burn_write_opts_new; burn_write_opts_new;
burn_write_opts_set_bdr_obs_exempt;
burn_write_opts_set_dvd_obs; burn_write_opts_set_dvd_obs;
burn_write_opts_set_fail21h_sev; burn_write_opts_set_fail21h_sev;
burn_write_opts_set_fillup; burn_write_opts_set_fillup;
@ -210,3 +213,13 @@ libdax_audioxtr_new;
libdax_audioxtr_read; libdax_audioxtr_read;
local: *; local: *;
}; };
LIBBURN4_1.5.8 {
burn_disc_get_sectors_v2;
burn_disc_track_lba_nwa_v2;
burn_drive_get_status_v2;
burn_get_read_capacity_v2;
burn_session_get_sectors_v2;
burn_track_get_sectors_v2;
} LIBBURN4;

View File

@ -158,7 +158,7 @@ static int libdax_audioxtr_identify_wav(struct libdax_audioxtr *o, int flag)
char buf[16]; char buf[16];
unsigned char *ubuf; unsigned char *ubuf;
/* check wether this is a MS WAVE file .wav */ /* check whether this is a MS WAVE file .wav */
/* info used: http://ccrma.stanford.edu/courses/422/projects/WaveFormat/ /* info used: http://ccrma.stanford.edu/courses/422/projects/WaveFormat/
https://en.wikipedia.org/wiki/WAV https://en.wikipedia.org/wiki/WAV
see summary in: doc/waveformat.txt see summary in: doc/waveformat.txt
@ -247,7 +247,7 @@ static int libdax_audioxtr_identify_au(struct libdax_audioxtr *o, int flag)
int ret,encoding; int ret,encoding;
char buf[24]; char buf[24];
/* Check wether this is a Sun Audio, .au file */ /* Check whether this is a Sun Audio, .au file */
/* info used: http://ccrma.stanford.edu/courses/422/projects/WaveFormat/ */ /* info used: http://ccrma.stanford.edu/courses/422/projects/WaveFormat/ */
if(o->fd!=0) { if(o->fd!=0) {

View File

@ -38,7 +38,7 @@ struct libdax_audioxtr;
/* Calls from applications (to be forwarded by libdax/libburn) */ /* Calls from applications (to be forwarded by libdax/libburn) */
/** Open an audio file, check wether suitable, create extractor object. /** Open an audio file, check whether suitable, create extractor object.
@param xtr Opaque handle to extractor. Gets attached extractor object. @param xtr Opaque handle to extractor. Gets attached extractor object.
@param path Address of the audio file to extract. "-" is stdin (but might @param path Address of the audio file to extract. "-" is stdin (but might
be not suitable for all futurely supported formats). be not suitable for all futurely supported formats).

View File

@ -1,7 +1,7 @@
/* libdax_msgs /* libdax_msgs
Message handling facility of libburn and libisofs. Message handling facility of libburn and libisofs.
Copyright (C) 2006-2016 Thomas Schmitt <scdbackup@gmx.net>, Copyright (C) 2006-2021 Thomas Schmitt <scdbackup@gmx.net>,
provided under GPL version 2 or later. provided under GPL version 2 or later.
*/ */
@ -425,7 +425,7 @@ Range "elmom" : 0x00010000 to 0x0001ffff
------------------------------------------------------------------------------ ------------------------------------------------------------------------------
Range "scdbackup" : 0x00020000 to 0x0002ffff Range "scdbackup" : 0x00020000 to 0x0002ffff
Acessing and defending drives: Accessing and defending drives:
0x00020001 (SORRY,LOW) = Cannot open busy device 0x00020001 (SORRY,LOW) = Cannot open busy device
0x00020002 (SORRY,HIGH) = Encountered error when closing drive 0x00020002 (SORRY,HIGH) = Encountered error when closing drive
@ -555,7 +555,7 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
0x0002016e (DEBUG,HIGH) = MODE SENSE page 2A too short 0x0002016e (DEBUG,HIGH) = MODE SENSE page 2A too short
0x0002016f (DEBUG,HIGH) = Unable to grab scanned drive 0x0002016f (DEBUG,HIGH) = Unable to grab scanned drive
0x00020170 (NOTE,HIGH) = Closing open session before writing new one 0x00020170 (NOTE,HIGH) = Closing open session before writing new one
0x00020171 (NOTE,HIGH) = Closing BD-R with accidentaly open session 0x00020171 (NOTE,HIGH) = Closing BD-R with accidentally open session
0x00020172 (SORRY,HIGH) = Read start address larger than number of readable blocks 0x00020172 (SORRY,HIGH) = Read start address larger than number of readable blocks
0x00020173 (FAILURE,HIGH) = Drive tells NWA smaller than last written address 0x00020173 (FAILURE,HIGH) = Drive tells NWA smaller than last written address
0x00020174 (SORRY,HIGH) = Fifo alignment does not allow desired read size 0x00020174 (SORRY,HIGH) = Fifo alignment does not allow desired read size
@ -580,7 +580,7 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
0x00020187 (NOTE,HIGH) = Track not marked as damaged. No action taken. 0x00020187 (NOTE,HIGH) = Track not marked as damaged. No action taken.
0x00020188 (FAILURE,HIGH) = Cannot close damaged track on given media type 0x00020188 (FAILURE,HIGH) = Cannot close damaged track on given media type
0x00020189 (FATAL,HIGH) = Drive is already grabbed by libburn 0x00020189 (FATAL,HIGH) = Drive is already grabbed by libburn
0x0002018a (SORRY,HIGH) = Timeout exceeded. Retry cancled. 0x0002018a (SORRY,HIGH) = Timeout exceeded. Retry canceled.
0x0002018b (FAILURE,HIGH) = Too many CD-TEXT packs 0x0002018b (FAILURE,HIGH) = Too many CD-TEXT packs
0x0002018c (FAILURE,HIGH) = CD-TEXT pack type out of range 0x0002018c (FAILURE,HIGH) = CD-TEXT pack type out of range
0x0002018d (FAILURE,HIGH) = CD-TEXT block number out of range 0x0002018d (FAILURE,HIGH) = CD-TEXT block number out of range
@ -616,6 +616,7 @@ Range "scdbackup" : 0x00020000 to 0x0002ffff
0x000201ab (WARN,HIGH) = Leaving burn_source_fifo object undisposed 0x000201ab (WARN,HIGH) = Leaving burn_source_fifo object undisposed
0x000201ac (NOTE,HIGH) = Drive currently does not offer Stream Recording 0x000201ac (NOTE,HIGH) = Drive currently does not offer Stream Recording
0x000201ad (NOTE,HIGH) = WRITE commands have been repeated 0x000201ad (NOTE,HIGH) = WRITE commands have been repeated
0x000201ae (FAILURE,HIGH) = Track size exceeds 4 TiB - 32 KiB
libdax_audioxtr: libdax_audioxtr:
@ -646,11 +647,11 @@ Range "vreixo" : 0x00030000 to 0x0003ffff
0x0003ffbc (FAILURE,HIGH) = Image already bootable 0x0003ffbc (FAILURE,HIGH) = Image already bootable
0x0003ffbb (FAILURE,HIGH) = Trying to use an invalid file as boot image 0x0003ffbb (FAILURE,HIGH) = Trying to use an invalid file as boot image
0x0003ff80 (FAILURE,HIGH) = Error on file operation 0x0003ff80 (FAILURE,HIGH) = Error on file operation
0x0003ff7f (FAILURE,HIGH) = Trying to open an already openned file 0x0003ff7f (FAILURE,HIGH) = Trying to open an already opened file
0x0003ff7e (FAILURE,HIGH) = Access to file is not allowed 0x0003ff7e (FAILURE,HIGH) = Access to file is not allowed
0x0003ff7d (FAILURE,HIGH) = Incorrect path to file 0x0003ff7d (FAILURE,HIGH) = Incorrect path to file
0x0003ff7c (FAILURE,HIGH) = The file does not exist in the filesystem 0x0003ff7c (FAILURE,HIGH) = The file does not exist in the filesystem
0x0003ff7b (FAILURE,HIGH) = Trying to read or close a file not openned 0x0003ff7b (FAILURE,HIGH) = Trying to read or close a file not opened
0x0003ff7a (FAILURE,HIGH) = Directory used where no dir is expected 0x0003ff7a (FAILURE,HIGH) = Directory used where no dir is expected
0x0003ff79 (FAILURE,HIGH) = File read error 0x0003ff79 (FAILURE,HIGH) = File read error
0x0003ff78 (FAILURE,HIGH) = Not dir used where a dir is expected 0x0003ff78 (FAILURE,HIGH) = Not dir used where a dir is expected
@ -701,7 +702,7 @@ X 0x00030203 (HINT,MEDIUM) = Unsupported El-Torito feature
X 0x00030204 (SORRY,HIGH) = Invalid file to be an El-Torito image X 0x00030204 (SORRY,HIGH) = Invalid file to be an El-Torito image
X 0x00030205 (WARNING,MEDIUM)= Cannot properly patch isolinux image X 0x00030205 (WARNING,MEDIUM)= Cannot properly patch isolinux image
X 0x00030206 (WARNING,MEDIUM)= Copying El-Torito from a previous image without X 0x00030206 (WARNING,MEDIUM)= Copying El-Torito from a previous image without
X enought info about it X enough info about it
X 0x00030301 (NOTE,MEDIUM) = Unsupported file type for Joliet tree X 0x00030301 (NOTE,MEDIUM) = Unsupported file type for Joliet tree

View File

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2016 Thomas Schmitt <scdbackup@gmx.net> Copyright (c) 2006 - 2024 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later. Provided under GPL version 2 or later.
*/ */
@ -109,7 +109,7 @@ extern struct libdax_msgs *libdax_messenger;
Error messages of class DEBUG appear because of inability to Error messages of class DEBUG appear because of inability to
read TOC or track info. Nevertheless, the written images verify. read TOC or track info. Nevertheless, the written images verify.
ts A61220 : Burned to a virgin DVD+RW by help of new mmc_format_unit() ts A61220 : Burned to a virgin DVD+RW by help of new mmc_format_unit()
(did not test wether it would work without). Burned to a (did not test whether it would work without). Burned to a
not completely formatted DVD+RW. (Had worked before without not completely formatted DVD+RW. (Had worked before without
mmc_format_unit() but i did not exceed the formatted range mmc_format_unit() but i did not exceed the formatted range
as reported by dvd+rw-mediainfo.) as reported by dvd+rw-mediainfo.)
@ -300,6 +300,14 @@ int mmc_four_char_to_int(unsigned char *data)
} }
/* ts C40226 */
unsigned int mmc_four_char_to_uint(unsigned char *data)
{
return (((unsigned int) data[0]) << 24) | (data[1] << 16) |
(data[2] << 8) | data[3];
}
/* ts A70201 */ /* ts A70201 */
int mmc_int_to_four_char(unsigned char *data, int num) int mmc_int_to_four_char(unsigned char *data, int num)
{ {
@ -311,6 +319,17 @@ int mmc_int_to_four_char(unsigned char *data, int num)
} }
/* ts C40226 */
int mmc_uint_to_four_char(unsigned char *data, unsigned int num)
{
data[0] = (num >> 24) & 0xff;
data[1] = (num >> 16) & 0xff;
data[2] = (num >> 8) & 0xff;
data[3] = num & 0xff;
return 1;
}
static int mmc_start_for_bit0 = 0; static int mmc_start_for_bit0 = 0;
/* @param flag bit0= the calling function should need no START UNIT. /* @param flag bit0= the calling function should need no START UNIT.
@ -502,7 +521,7 @@ int mmc_get_nwa(struct burn_drive *d, int trackno, int *lba, int *nwa)
sprintf(msg, "Upcoming track: "); sprintf(msg, "Upcoming track: ");
if (d->current_profile == 0x1a || d->current_profile == 0x13 || if (d->current_profile == 0x1a || d->current_profile == 0x13 ||
d->current_profile == 0x12 || d->current_profile == 0x43) { d->current_profile == 0x12 || d->current_profile == 0x43) {
/* overwriteable */ /* overwritable */
*lba = *nwa = num = 0; *lba = *nwa = num = 0;
} else if (data[5] & 32) { /* ts B10534 : MMC-5 6.27.3.7 Damage Bit */ } else if (data[5] & 32) { /* ts B10534 : MMC-5 6.27.3.7 Damage Bit */
@ -747,7 +766,8 @@ ex:;
*/ */
static int mmc_wait_for_buffer_free(struct burn_drive *d, struct buffer *buf) static int mmc_wait_for_buffer_free(struct burn_drive *d, struct buffer *buf)
{ {
int usec= 0, need, reported_3s = 0, first_wait = 1; int usec= 0, reported_3s = 0, first_wait = 1;
off_t need;
struct timeval t0,tnow; struct timeval t0,tnow;
double max_fac, min_fac, waiting; double max_fac, min_fac, waiting;
@ -926,11 +946,11 @@ static int print_time(int flag)
#endif /* Libburn_write_time_debuG */ #endif /* Libburn_write_time_debuG */
int mmc_write(struct burn_drive *d, int start, struct buffer *buf) int mmc_write(struct burn_drive *d, off_t start_long, struct buffer *buf)
{ {
int cancelled; int cancelled;
struct command *c; struct command *c;
int len, key, asc, ascq; int len, key, asc, ascq, start;
char *msg = NULL; char *msg = NULL;
#ifdef Libburn_write_time_debuG #ifdef Libburn_write_time_debuG
@ -942,6 +962,16 @@ fprintf(stderr, "libburn_DEBUG: buffer sectors= %d bytes= %d\n",
buf->sectors, buf->bytes); buf->sectors, buf->bytes);
*/ */
if (start_long > (off_t) 0x7fffffff) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002012d,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
"Exceeding range of signed integer block addresses",
0, 0);
d->cancel = 1;
return BE_CANCELLED;
}
start = start_long;
c = &(d->casual_command); c = &(d->casual_command);
@ -963,26 +993,18 @@ fprintf(stderr, "libburn_DEBUG: buffer sectors= %d bytes= %d\n",
return BE_CANCELLED; return BE_CANCELLED;
/* ts A70215 */ /* ts A70215 */
if (d->media_lba_limit > 0 && start >= d->media_lba_limit) { if (d->media_lba_limit > 0 && start >= d->media_lba_limit &&
!d->write_opts->force_is_set) {
msg = calloc(1, 320); msg = calloc(1, 320);
if (msg != NULL) { if (msg != NULL) {
sprintf(msg, sprintf(msg,
"Exceeding range of permissible write addresses (%d >= %d)", "Exceeding range of permissible write addresses (%d >= %d)",
start, d->media_lba_limit); start, d->media_lba_limit);
libdax_msgs_submit(libdax_messenger, d->global_index, libdax_msgs_submit(libdax_messenger, d->global_index,
0x0002012d, 0x0002012d,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH, LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0); msg, 0, 0);
strcpy(msg, "CDB= ");
if (spc_human_readable_cmd(c, msg + strlen(msg),
320 - strlen(msg), 1) > 0) {
libdax_msgs_submit(libdax_messenger,
d->global_index, 0x0002012d,
LIBDAX_MSGS_SEV_FATAL,
LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
}
free(msg); free(msg);
} }
d->cancel = 1; /* No need for mutexing because atomic */ d->cancel = 1; /* No need for mutexing because atomic */
@ -1054,7 +1076,7 @@ fprintf(stderr, "libburn_DEBUG: buffer sectors= %d bytes= %d\n",
*/ */
if (d->current_profile == 0x14 && d->write_opts != NULL && if (d->current_profile == 0x14 && d->write_opts != NULL &&
(d->progress.buffer_capacity == 0 || (d->progress.buffer_capacity == 0 ||
start < (int) d->progress.buffer_capacity / 2048) && start < (off_t) d->progress.buffer_capacity / 2048) &&
key == 5 && asc == 0x64 && ascq == 0) { key == 5 && asc == 0x64 && ascq == 0) {
if (d->write_opts->write_type == BURN_WRITE_TAO) { if (d->write_opts->write_type == BURN_WRITE_TAO) {
d->was_feat21h_failure = 1 + (start == 0); d->was_feat21h_failure = 1 + (start == 0);
@ -1095,10 +1117,11 @@ int mmc_fake_toc_entry(struct burn_toc_entry *entry, int session_number,
unsigned char *size_data, unsigned char *start_data, unsigned char *size_data, unsigned char *start_data,
unsigned char *last_adr_data) unsigned char *last_adr_data)
{ {
int min, sec, frames, num; int min, sec, frames;
unsigned int num;
/* mark DVD extensions and Track Info extension as valid */ /* mark extensions as valid: DVD, Track Info, Long block address */
entry->extensions_valid |= (1 | 2); entry->extensions_valid |= (1 | 2 | 8);
/* defaults are as of mmc5r03.pdf 6.26.3.2.4 Fabricated TOC */ /* defaults are as of mmc5r03.pdf 6.26.3.2.4 Fabricated TOC */
entry->session = session_number & 0xff; entry->session = session_number & 0xff;
@ -1108,9 +1131,16 @@ int mmc_fake_toc_entry(struct burn_toc_entry *entry, int session_number,
entry->tno = 0; entry->tno = 0;
entry->point = track_number & 0xff; entry->point = track_number & 0xff;
entry->point_msb = (track_number >> 8) & 0xff; entry->point_msb = (track_number >> 8) & 0xff;
num = mmc_four_char_to_int(size_data); num = mmc_four_char_to_uint(size_data);
entry->track_blocks = num; if (num < 0x80000000) {
burn_lba_to_msf(num, &min, &sec, &frames); entry->track_blocks = num;
burn_lba_to_msf(num, &min, &sec, &frames);
} else {
entry->track_blocks = -1;
min = 477218; /* ~=LBA 0x7fffffff */
sec = frames = 0;
}
entry->long_track_blocks = num;
if (min > 255) { if (min > 255) {
min = 255; min = 255;
sec = 255; sec = 255;
@ -1120,9 +1150,16 @@ int mmc_fake_toc_entry(struct burn_toc_entry *entry, int session_number,
entry->sec = sec; entry->sec = sec;
entry->frame = frames; entry->frame = frames;
entry->zero = 0; entry->zero = 0;
num = mmc_four_char_to_int(start_data); num = mmc_four_char_to_uint(start_data);
entry->start_lba = num; if (num < 0x80000000) {
burn_lba_to_msf(num, &min, &sec, &frames); entry->start_lba = num;
burn_lba_to_msf(num, &min, &sec, &frames);
} else {
entry->start_lba = -1;
min = 477218;
sec = frames = 0;
}
entry->long_start_lba = num;
if (min > 255) { if (min > 255) {
min = 255; min = 255;
sec = 255; sec = 255;
@ -1131,7 +1168,13 @@ int mmc_fake_toc_entry(struct burn_toc_entry *entry, int session_number,
entry->pmin = min; entry->pmin = min;
entry->psec = sec; entry->psec = sec;
entry->pframe = frames; entry->pframe = frames;
entry->last_recorded_address = mmc_four_char_to_int(last_adr_data); num = mmc_four_char_to_uint(last_adr_data);
if (num < 0x80000000) {
entry->last_recorded_address = num;
} else {
entry->last_recorded_address = -1;
}
entry->long_last_rec_adr = num;
return 1; return 1;
} }
@ -1145,7 +1188,7 @@ static int mmc_read_toc_fmt0_al(struct burn_drive *d, int *alloc_len)
struct buffer *buf = NULL; struct buffer *buf = NULL;
struct command *c = NULL; struct command *c = NULL;
int dlen, i, old_alloc_len, session_number, prev_session = -1, ret; int dlen, i, old_alloc_len, session_number, prev_session = -1, ret;
int lba, size; unsigned int lba, size;
unsigned char *tdata, size_data[4], start_data[4], end_data[4]; unsigned char *tdata, size_data[4], start_data[4], end_data[4];
if (*alloc_len < 4) if (*alloc_len < 4)
@ -1224,11 +1267,11 @@ err_ex:;
if (session_number != prev_session && prev_session > 0) { if (session_number != prev_session && prev_session > 0) {
/* leadout entry previous session */ /* leadout entry previous session */
entry = &(d->toc_entry[(i - 1) + prev_session]); entry = &(d->toc_entry[(i - 1) + prev_session]);
lba = mmc_four_char_to_int(start_data) + lba = mmc_four_char_to_uint(start_data) +
mmc_four_char_to_int(size_data); mmc_four_char_to_uint(size_data);
mmc_int_to_four_char(start_data, lba); mmc_uint_to_four_char(start_data, lba);
mmc_int_to_four_char(size_data, 0); mmc_uint_to_four_char(size_data, 0);
mmc_int_to_four_char(end_data, lba - 1); mmc_uint_to_four_char(end_data, lba - 1);
mmc_fake_toc_entry(entry, prev_session, 0xA2, mmc_fake_toc_entry(entry, prev_session, 0xA2,
size_data, start_data, end_data); size_data, start_data, end_data);
entry->min= entry->sec= entry->frame= 0; entry->min= entry->sec= entry->frame= 0;
@ -1253,11 +1296,11 @@ err_ex:;
memcpy(start_data, tdata + 4, 4); memcpy(start_data, tdata + 4, 4);
/* size_data are estimated from next track start */ /* size_data are estimated from next track start */
memcpy(size_data, tdata + 8 + 4, 4); memcpy(size_data, tdata + 8 + 4, 4);
mmc_int_to_four_char(end_data, mmc_uint_to_four_char(end_data,
mmc_four_char_to_int(size_data) - 1); mmc_four_char_to_uint(size_data) - 1);
size = mmc_four_char_to_int(size_data) - size = mmc_four_char_to_uint(size_data) -
mmc_four_char_to_int(start_data); mmc_four_char_to_uint(start_data);
mmc_int_to_four_char(size_data, size); mmc_uint_to_four_char(size_data, size);
mmc_fake_toc_entry(entry, session_number, i + 1, mmc_fake_toc_entry(entry, session_number, i + 1,
size_data, start_data, end_data); size_data, start_data, end_data);
if (prev_session != session_number) if (prev_session != session_number)
@ -1270,9 +1313,9 @@ err_ex:;
tdata = c->page->data + 4 + d->last_track_no * 8; tdata = c->page->data + 4 + d->last_track_no * 8;
entry = &(d->toc_entry[(d->last_track_no - 1) + prev_session]); entry = &(d->toc_entry[(d->last_track_no - 1) + prev_session]);
memcpy(start_data, tdata + 4, 4); memcpy(start_data, tdata + 4, 4);
mmc_int_to_four_char(size_data, 0); mmc_uint_to_four_char(size_data, 0);
mmc_int_to_four_char(end_data, mmc_uint_to_four_char(end_data,
mmc_four_char_to_int(start_data) - 1); mmc_four_char_to_uint(start_data) - 1);
mmc_fake_toc_entry(entry, prev_session, 0xA2, mmc_fake_toc_entry(entry, prev_session, 0xA2,
size_data, start_data, end_data); size_data, start_data, end_data);
entry->min= entry->sec= entry->frame= 0; entry->min= entry->sec= entry->frame= 0;
@ -1309,7 +1352,8 @@ int mmc_fake_toc(struct burn_drive *d)
struct burn_session *session; struct burn_session *session;
struct burn_toc_entry *entry; struct burn_toc_entry *entry;
struct buffer *buf = NULL; struct buffer *buf = NULL;
int i, session_number, prev_session = -1, ret, lba, alloc_len = 34; int i, session_number, prev_session = -1, ret, alloc_len = 34;
unsigned int lba;
unsigned char *tdata, size_data[4], start_data[4], end_data[4]; unsigned char *tdata, size_data[4], start_data[4], end_data[4];
char *msg = NULL; char *msg = NULL;
@ -1414,11 +1458,11 @@ int mmc_fake_toc(struct burn_drive *d)
if (session_number != prev_session && prev_session > 0) { if (session_number != prev_session && prev_session > 0) {
/* leadout entry previous session */ /* leadout entry previous session */
entry = &(d->toc_entry[(i - 1) + prev_session]); entry = &(d->toc_entry[(i - 1) + prev_session]);
lba = mmc_four_char_to_int(start_data) + lba = mmc_four_char_to_uint(start_data) +
mmc_four_char_to_int(size_data); mmc_four_char_to_uint(size_data);
mmc_int_to_four_char(start_data, lba); mmc_uint_to_four_char(start_data, lba);
mmc_int_to_four_char(size_data, 0); mmc_uint_to_four_char(size_data, 0);
mmc_int_to_four_char(end_data, lba - 1); mmc_uint_to_four_char(end_data, lba - 1);
mmc_fake_toc_entry(entry, prev_session, 0xA2, mmc_fake_toc_entry(entry, prev_session, 0xA2,
size_data, start_data, end_data); size_data, start_data, end_data);
entry->min= entry->sec= entry->frame= 0; entry->min= entry->sec= entry->frame= 0;
@ -1439,7 +1483,7 @@ int mmc_fake_toc(struct burn_drive *d)
if (i == d->last_track_no - 1) { if (i == d->last_track_no - 1) {
/* ts A70212 : Last track field Free Blocks */ /* ts A70212 : Last track field Free Blocks */
burn_drive_set_media_capacity_remaining(d, burn_drive_set_media_capacity_remaining(d,
((off_t) mmc_four_char_to_int(tdata + 16)) * ((off_t) mmc_four_char_to_uint(tdata + 16)) *
((off_t) 2048)); ((off_t) 2048));
d->media_lba_limit = 0; d->media_lba_limit = 0;
} }
@ -1485,11 +1529,11 @@ int mmc_fake_toc(struct burn_drive *d)
if (prev_session > 0 && prev_session <= d->disc->sessions) { if (prev_session > 0 && prev_session <= d->disc->sessions) {
/* leadout entry of last session of closed disc */ /* leadout entry of last session of closed disc */
entry = &(d->toc_entry[(d->last_track_no - 1) + prev_session]); entry = &(d->toc_entry[(d->last_track_no - 1) + prev_session]);
lba = mmc_four_char_to_int(start_data) + lba = mmc_four_char_to_uint(start_data) +
mmc_four_char_to_int(size_data); mmc_four_char_to_uint(size_data);
mmc_int_to_four_char(start_data, lba); mmc_uint_to_four_char(start_data, lba);
mmc_int_to_four_char(size_data, 0); mmc_uint_to_four_char(size_data, 0);
mmc_int_to_four_char(end_data, lba - 1); mmc_uint_to_four_char(end_data, lba - 1);
mmc_fake_toc_entry(entry, prev_session, 0xA2, mmc_fake_toc_entry(entry, prev_session, 0xA2,
size_data, start_data, end_data); size_data, start_data, end_data);
entry->min= entry->sec= entry->frame= 0; entry->min= entry->sec= entry->frame= 0;
@ -1581,7 +1625,7 @@ static int mmc_read_toc_al(struct burn_drive *d, int *alloc_len)
/* ts A61020 : this snaps on non-blank DVD media */ /* ts A61020 : this snaps on non-blank DVD media */
/* ts A61106 : also snaps on CD with unclosed track/session */ /* ts A61106 : also snaps on CD with unclosed track/session */
/* Very unsure wether this old measure is ok. /* Very unsure whether this old measure is ok.
Obviously higher levels do not care about this. Obviously higher levels do not care about this.
outdated info: DVD+RW burns go on after passing through here. outdated info: DVD+RW burns go on after passing through here.
@ -1740,8 +1784,8 @@ static int mmc_read_toc_al(struct burn_drive *d, int *alloc_len)
TOC format 2 always reports 2 blocks more than are readable. TOC format 2 always reports 2 blocks more than are readable.
So here it is possible to check and mark as trusted. So here it is possible to check and mark as trusted.
*/ */
if (highest_leadout > 0 && d->media_read_capacity != 0x7fffffff && if (highest_leadout > 0 && d->media_read_capacity != 0x7fffffffffffffff
!d->mr_capacity_trusted) { && !d->mr_capacity_trusted) {
if (highest_leadout - 3 == d->media_read_capacity) { if (highest_leadout - 3 == d->media_read_capacity) {
d->mr_capacity_trusted = 1; d->mr_capacity_trusted = 1;
libdax_msgs_submit(libdax_messenger, d->global_index, libdax_msgs_submit(libdax_messenger, d->global_index,
@ -1782,12 +1826,12 @@ void mmc_read_toc(struct burn_drive *d)
} }
/* ts A70131 : This tries to get the start of the last complete session */ /* ts C40226 : long address reply version of mmc_read_multi_session_c1 */
/* man mkisofs , option -C : /* man mkisofs , option -C :
The first number is the sector number of the first sector in The first number is the sector number of the first sector in
the last session of the disk that should be appended to. the last session of the disk that should be appended to.
*/ */
int mmc_read_multi_session_c1(struct burn_drive *d, int *trackno, int *start) int mmc_read_msc1_long(struct burn_drive *d, int *trackno, off_t *start)
{ {
struct buffer *buf = NULL; struct buffer *buf = NULL;
struct command *c = NULL; struct command *c = NULL;
@ -1820,7 +1864,11 @@ int mmc_read_multi_session_c1(struct burn_drive *d, int *trackno, int *start)
continue; continue;
burn_track_get_entry(tracks[0], &toc_entry); burn_track_get_entry(tracks[0], &toc_entry);
if (toc_entry.extensions_valid & 1) { /* DVD extension valid */ if (toc_entry.extensions_valid & 1) { /* DVD extension valid */
*start = toc_entry.start_lba; if (toc_entry.extensions_valid & 8) { /* Long adr */
*start = toc_entry.long_start_lba;
} else {
*start = toc_entry.start_lba;
}
*trackno = (toc_entry.point_msb << 8)| toc_entry.point; *trackno = (toc_entry.point_msb << 8)| toc_entry.point;
} else { } else {
*start = burn_msf_to_lba(toc_entry.pmin, *start = burn_msf_to_lba(toc_entry.pmin,
@ -1855,7 +1903,7 @@ inquire_drive:;
tdata = c->page->data + 4; tdata = c->page->data + 4;
*trackno = tdata[2]; *trackno = tdata[2];
*start = mmc_four_char_to_int(tdata + 4); *start = mmc_four_char_to_uint(tdata + 4);
ret = 1; ret = 1;
ex:; ex:;
BURN_FREE_MEM(buf); BURN_FREE_MEM(buf);
@ -1864,6 +1912,24 @@ ex:;
} }
/* ts A70131 : This tries to get the start of the last complete session */
int mmc_read_multi_session_c1(struct burn_drive *d, int *trackno, int *start)
{
int ret;
off_t num;
ret = mmc_read_msc1_long(d, trackno, &num);
if (ret <= 0)
return ret;
if(num >= 0x80000000) {
*start = 0x7fffffff;
return 0;
}
*start = num;
return 1;
}
/* ts A61201 */ /* ts A61201 */
char *mmc_obtain_profile_name(int profile_number) char *mmc_obtain_profile_name(int profile_number)
{ {
@ -1959,7 +2025,7 @@ static int mmc_read_disc_info_al(struct burn_drive *d, int *alloc_len)
d->media_lba_limit = 0; d->media_lba_limit = 0;
/* ts A81210 */ /* ts A81210 */
d->media_read_capacity = 0x7fffffff; d->media_read_capacity = 0x7fffffffffffffff;
d->mr_capacity_trusted = -1; d->mr_capacity_trusted = -1;
/* ts A61202 */ /* ts A61202 */
@ -2635,7 +2701,7 @@ int mmc_read_cd(struct burn_drive *d, int start, int len,
int sec_type, int main_ch, int sec_type, int main_ch,
const struct burn_read_opts *o, struct buffer *buf, int flag) const struct burn_read_opts *o, struct buffer *buf, int flag)
{ {
int temp, req, ret, dap_bit; int temp, req, ret, dap_bit, len_shift;
int subcodes_audio = 0, subcodes_data = 0; int subcodes_audio = 0, subcodes_data = 0;
struct command *c; struct command *c;
@ -2674,6 +2740,9 @@ int mmc_read_cd(struct burn_drive *d, int start, int len,
} }
scsi_init_command(c, MMC_READ_CD, sizeof(MMC_READ_CD)); scsi_init_command(c, MMC_READ_CD, sizeof(MMC_READ_CD));
/* (this was never tested with anything but sec_type = 1 = CD-DA) */
if(sec_type == 1 && main_ch == 0x10)
c->dxfer_len = len * 2352;
c->retry = 1; c->retry = 1;
c->opcode[1] = ((sec_type & 7) << 2) | ((!!dap_bit) << 1); c->opcode[1] = ((sec_type & 7) << 2) | ((!!dap_bit) << 1);
temp = start; temp = start;
@ -2684,11 +2753,12 @@ int mmc_read_cd(struct burn_drive *d, int start, int len,
c->opcode[3] = temp & 0xFF; c->opcode[3] = temp & 0xFF;
temp >>= 8; temp >>= 8;
c->opcode[2] = temp & 0xFF; c->opcode[2] = temp & 0xFF;
c->opcode[8] = len & 0xFF; len_shift = len;
len >>= 8; c->opcode[8] = len_shift & 0xFF;
c->opcode[7] = len & 0xFF; len_shift >>= 8;
len >>= 8; c->opcode[7] = len_shift & 0xFF;
c->opcode[6] = len & 0xFF; len_shift >>= 8;
c->opcode[6] = len_shift & 0xFF;
req = main_ch & 0xf8; req = main_ch & 0xf8;
#ifdef Libburn_mmc_report_recovereD #ifdef Libburn_mmc_report_recovereD
@ -2832,6 +2902,8 @@ int mmc_set_streaming(struct burn_drive *d,
pd = c->page->data; pd = c->page->data;
pd[0] = 0; /* WRC=0 (Default Rotation Control), RDD=Exact=RA=0 */ pd[0] = 0; /* WRC=0 (Default Rotation Control), RDD=Exact=RA=0 */
if (d->set_streaming_exact_bit)
pd[0] |= 2; /* Exact= 1 */
if (w_speed == 0) if (w_speed == 0)
w_speed = 0x10000000; /* ~ 2 TB/s */ w_speed = 0x10000000; /* ~ 2 TB/s */
@ -2849,8 +2921,9 @@ int mmc_set_streaming(struct burn_drive *d,
} else } else
eff_end_lba = end_lba; eff_end_lba = end_lba;
sprintf(msg, "mmc_set_streaming: end_lba=%d , r=%d , w=%d", sprintf(msg,
eff_end_lba, r_speed, w_speed); "mmc_set_streaming: end_lba=%d , r=%d , w=%d , exact=%d",
eff_end_lba, r_speed, w_speed, !!(pd[0] & 2));
libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002, libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
msg, 0, 0); msg, 0, 0);
@ -2886,6 +2959,8 @@ int mmc_set_streaming(struct burn_drive *d,
LIBDAX_MSGS_SEV_DEBUG : LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_SEV_DEBUG : LIBDAX_MSGS_SEV_SORRY,
LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0); LIBDAX_MSGS_PRIO_HIGH, msg, 0, 0);
} }
if (key != 0)
d->set_streaming_err = 1;
{ret = 0; goto ex;} {ret = 0; goto ex;}
} }
ret = 1; ret = 1;
@ -2963,8 +3038,8 @@ void mmc_set_speed(struct burn_drive *d, int r, int w)
/* ts A61221 : try to set DVD speed via command B6h */ /* ts A61221 : try to set DVD speed via command B6h */
if (strstr(d->current_profile_text, "DVD") == d->current_profile_text if (strstr(d->current_profile_text, "DVD") == d->current_profile_text
|| || strstr(d->current_profile_text, "BD") == d->current_profile_text
strstr(d->current_profile_text, "BD") == d->current_profile_text) { || d->set_streaming_exact_bit) {
ret = mmc_set_streaming(d, r, w, end_lba); ret = mmc_set_streaming(d, r, w, end_lba);
if (ret != 0) if (ret != 0)
return; /* success or really fatal failure */ return; /* success or really fatal failure */
@ -3642,7 +3717,7 @@ int mmc_read_buffer_capacity(struct burn_drive *d)
d->pessimistic_buffer_free = d->progress.buffer_available; d->pessimistic_buffer_free = d->progress.buffer_available;
d->pbf_altered = 0; d->pbf_altered = 0;
if (d->progress.buffered_bytes >= d->progress.buffer_capacity){ if (d->progress.buffered_bytes >= d->progress.buffer_capacity){
double fill; off_t fill;
fill = d->progress.buffer_capacity fill = d->progress.buffer_capacity
- d->progress.buffer_available; - d->progress.buffer_available;
@ -3660,7 +3735,7 @@ ex:;
/* ts A61219 : learned much from dvd+rw-tools-7.0: plus_rw_format() /* ts A61219 : learned much from dvd+rw-tools-7.0: plus_rw_format()
and mmc5r03c.pdf, 6.5 FORMAT UNIT */ and mmc5r03c.pdf, 6.5 FORMAT UNIT */
/* /*
@param size The size (in bytes) to be sent with the FORMAT comand @param size The size (in bytes) to be sent with the FORMAT command
@param flag bit1+2: size mode @param flag bit1+2: size mode
0 = use parameter size as far as it makes sense 0 = use parameter size as far as it makes sense
1 = insist in size 0 even if there is a better default known 1 = insist in size 0 even if there is a better default known
@ -3715,7 +3790,7 @@ int mmc_format_unit(struct burn_drive *d, off_t size, int flag)
num_of_blocks = size / 2048; num_of_blocks = size / 2048;
mmc_int_to_four_char(c->page->data + 4, num_of_blocks); mmc_int_to_four_char(c->page->data + 4, num_of_blocks);
if (flag & 128) { /* explicitely chosen format descriptor */ if (flag & 128) { /* explicitly chosen format descriptor */
/* use case: the app knows what to do */ /* use case: the app knows what to do */
ret = mmc_read_format_capacities(d, -1); ret = mmc_read_format_capacities(d, -1);
@ -4902,7 +4977,7 @@ int mmc_read_capacity(struct burn_drive *d)
BURN_ALLOC_MEM(buf, struct buffer, 1); BURN_ALLOC_MEM(buf, struct buffer, 1);
BURN_ALLOC_MEM(c, struct command, 1); BURN_ALLOC_MEM(c, struct command, 1);
d->media_read_capacity = 0x7fffffff; d->media_read_capacity = 0x7fffffffffffffff;
d->mr_capacity_trusted = -1; d->mr_capacity_trusted = -1;
mmc_start_if_needed(d, 1); mmc_start_if_needed(d, 1);
if (mmc_function_spy(d, "mmc_read_capacity") <= 0) if (mmc_function_spy(d, "mmc_read_capacity") <= 0)
@ -4916,11 +4991,7 @@ int mmc_read_capacity(struct burn_drive *d)
c->page->sectors = 0; c->page->sectors = 0;
c->dir = FROM_DRIVE; c->dir = FROM_DRIVE;
d->issue_command(d, c); d->issue_command(d, c);
d->media_read_capacity = mmc_four_char_to_int(c->page->data); d->media_read_capacity = mmc_four_char_to_uint(c->page->data);
if (d->media_read_capacity < 0) {
d->media_read_capacity = 0x7fffffff;
{ret = 0; goto ex;}
}
if (d->current_profile >= 0x08 && d->current_profile <= 0x0A) if (d->current_profile >= 0x08 && d->current_profile <= 0x0A)
d->mr_capacity_trusted = 0; d->mr_capacity_trusted = 0;
else else
@ -5440,7 +5511,7 @@ int mmc_setup_drive(struct burn_drive *d)
d->last_track_no = 1; d->last_track_no = 1;
d->media_capacity_remaining = 0; d->media_capacity_remaining = 0;
d->media_lba_limit = 0; d->media_lba_limit = 0;
d->media_read_capacity = 0x7fffffff; d->media_read_capacity = 0x7fffffffffffffff;
d->mr_capacity_trusted = 0; d->mr_capacity_trusted = 0;
d->pessimistic_buffer_free = 0; d->pessimistic_buffer_free = 0;
d->pbf_altered = 0; d->pbf_altered = 0;

View File

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2014 Thomas Schmitt <scdbackup@gmx.net> Copyright (c) 2006 - 2024 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later. Provided under GPL version 2 or later.
*/ */
@ -27,7 +27,7 @@ void mmc_close_disc(struct burn_write_opts *o);
void mmc_close(struct burn_drive *, int session, int track); void mmc_close(struct burn_drive *, int session, int track);
void mmc_get_event(struct burn_drive *); void mmc_get_event(struct burn_drive *);
int mmc_write(struct burn_drive *, int start, struct buffer *buf); int mmc_write(struct burn_drive *, off_t start, struct buffer *buf);
void mmc_write_12(struct burn_drive *d, int start, struct buffer *buf); void mmc_write_12(struct burn_drive *d, int start, struct buffer *buf);
void mmc_sync_cache(struct burn_drive *); void mmc_sync_cache(struct burn_drive *);
void mmc_load(struct burn_drive *); void mmc_load(struct burn_drive *);
@ -78,6 +78,8 @@ int mmc_compose_mode_page_5(struct burn_drive *d,
/* ts A70201 */ /* ts A70201 */
int mmc_four_char_to_int(unsigned char *data); int mmc_four_char_to_int(unsigned char *data);
/* ts C40226 */
unsigned int mmc_four_char_to_uint(unsigned char *data);
/* ts A70201 : /* ts A70201 :
Common track info fetcher for mmc_get_nwa() and mmc_fake_toc() Common track info fetcher for mmc_get_nwa() and mmc_fake_toc()

View File

@ -55,6 +55,7 @@ struct burn_write_opts *burn_write_opts_new(struct burn_drive *drive)
opts->obs_pad = 0; opts->obs_pad = 0;
#endif #endif
opts->bdr_obs_exempt = 0;
opts->start_byte = -1; opts->start_byte = -1;
opts->fill_up_media = 0; opts->fill_up_media = 0;
opts->force_is_set = 0; opts->force_is_set = 0;
@ -535,17 +536,25 @@ void burn_write_opts_set_obs_pad(struct burn_write_opts *opts, int pad)
} }
/* ts A91115: API */ /* ts C10909: API */
void burn_write_opts_set_stdio_fsync(struct burn_write_opts *opts, int rythm) void burn_write_opts_set_bdr_obs_exempt(struct burn_write_opts *opts,
int value)
{ {
if (rythm == -1) opts->bdr_obs_exempt = !!value;
}
/* ts A91115: API */
void burn_write_opts_set_stdio_fsync(struct burn_write_opts *opts, int rhythm)
{
if (rhythm == -1)
opts->stdio_fsync_size = -1; /* never */ opts->stdio_fsync_size = -1; /* never */
else if (rythm == 0) else if (rhythm == 0)
opts->stdio_fsync_size = Libburn_stdio_fsync_limiT; opts->stdio_fsync_size = Libburn_stdio_fsync_limiT;
else if (rythm == 1) else if (rhythm == 1)
opts->stdio_fsync_size = 0; /* only at end of writing */ opts->stdio_fsync_size = 0; /* only at end of writing */
else if (rythm >= 32) else if (rhythm >= 32)
opts->stdio_fsync_size = rythm; opts->stdio_fsync_size = rhythm;
} }

View File

@ -46,14 +46,17 @@ struct burn_write_opts
2 indicates burn_write_opts_set_obs_pad(,1) 2 indicates burn_write_opts_set_obs_pad(,1)
*/ */
/* 1= do not apply obs_pad=1 to BD-R if not stream recording. */
int bdr_obs_exempt;
/* ts A61222 : Start address for media which offer a choice */ /* ts A61222 : Start address for media which offer a choice */
off_t start_byte; off_t start_byte;
/* ts A70213 : Wether to fill up the available space on media */ /* ts A70213 : Whether to fill up the available space on media */
int fill_up_media; int fill_up_media;
/* ts A70303 : Wether to override conformance checks: /* ts A70303 : Whether to override conformance checks:
- the check wether CD write+block type is supported by the drive - the check whether CD write+block type is supported by the drive
*/ */
int force_is_set; int force_is_set;

View File

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2014 Thomas Schmitt <scdbackup@gmx.net> Copyright (c) 2006 - 2024 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later. Provided under GPL version 2 or later.
*/ */
@ -286,7 +286,7 @@ void burn_packet_process(struct burn_drive *d, unsigned char *data,
*//* write(o->datafd, data, 2352); */ *//* write(o->datafd, data, 2352); */
} }
/* so yeah, when you uncomment these, make them write zeros insted of crap /* so yeah, when you uncomment these, make them write zeros instead of crap
static void write_empty_sector(int fd) static void write_empty_sector(int fd)
{ {
static char sec[2352], initialized = 0; static char sec[2352], initialized = 0;
@ -492,13 +492,13 @@ int burn_read_data(struct burn_drive *d, off_t byte_address,
msg, 0, 0); msg, 0, 0);
{ret = 0; goto ex;} {ret = 0; goto ex;}
} }
if (d->media_read_capacity != 0x7fffffff && byte_address >= if (d->media_read_capacity != 0x7fffffffffffffff &&
((off_t) d->media_read_capacity + (off_t) 1) * (off_t) 2048) { byte_address >= (d->media_read_capacity + 1) * (off_t) 2048) {
if (!(flag & 2)) { if (!(flag & 2)) {
sprintf(msg, sprintf(msg,
"Read start address %ds larger than number of readable blocks %d", "Read start address %.fs larger than number of readable blocks %.f",
(int) (byte_address / 2048 + !!(byte_address % 2048)), (double) (byte_address / 2048 + !!(byte_address % 2048)),
d->media_read_capacity + 1); (double) (d->media_read_capacity + 1));
libdax_msgs_submit(libdax_messenger, d->global_index, libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020172, (flag & 32) ? 0x00020172, (flag & 32) ?
LIBDAX_MSGS_SEV_DEBUG : LIBDAX_MSGS_SEV_SORRY, LIBDAX_MSGS_SEV_DEBUG : LIBDAX_MSGS_SEV_SORRY,

View File

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2016 Thomas Schmitt <scdbackup@gmx.net> Copyright (c) 2006 - 2021 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later. Provided under GPL version 2 or later.
*/ */
@ -193,7 +193,9 @@ static void get_bytes(struct burn_track *track, int count, unsigned char *data)
off_t missing, inp_block_size, track_blocks; off_t missing, inp_block_size, track_blocks;
inp_block_size = burn_sector_length(track->mode); inp_block_size = burn_sector_length(track->mode);
track_blocks = burn_track_get_sectors_2(track, 1); track_blocks = burn_track_get_sectors_2_v2(track, 1);
if (track_blocks < 0)
track_blocks = 0;
missing = track_blocks * inp_block_size - track->sourcecount; missing = track_blocks * inp_block_size - track->sourcecount;
sprintf(msg, sprintf(msg,
"Premature end of input encountered. Missing: %.f bytes", "Premature end of input encountered. Missing: %.f bytes",
@ -923,7 +925,7 @@ void process_q(struct burn_drive *d, unsigned char *q)
break; break;
default: default:
/* ts A61009 : if reactivated then witout Assert */ /* ts A61009 : if reactivated then without Assert */
a ssert(0); a ssert(0);
} }
} }

View File

@ -144,7 +144,7 @@ int scsi_enumerate_drives(void)
} }
/** Tells wether libburn has the given drive in use or exclusively reserved. /** 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 If it is "open" then libburn will eventually call sg_release() on it when
it is time to give up usage and reservation. it is time to give up usage and reservation.
*/ */
@ -180,7 +180,7 @@ int sg_release(struct burn_drive *d)
} }
/** Sends a SCSI command to the drive, receives reply and evaluates wether /** Sends a SCSI command to the drive, receives reply and evaluates whether
the command succeeded or shall be retried or finally failed. the command succeeded or shall be retried or finally failed.
Returned SCSI errors shall not lead to a return value indicating failure. Returned SCSI errors shall not lead to a return value indicating failure.
The callers get notified by c->error. An SCSI failure which leads not to The callers get notified by c->error. An SCSI failure which leads not to
@ -213,7 +213,7 @@ int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
} }
/** Tells wether a text is a persistent address as listed by the enumeration /** Tells whether a text is a persistent address as listed by the enumeration
functions. functions.
*/ */
int sg_is_enumerable_adr(char *adr) int sg_is_enumerable_adr(char *adr)

View File

@ -47,8 +47,8 @@ sg_initialize() performs global initialization of the SCSI transport
facilities. Checks for compatibility of supporting facilities. Checks for compatibility of supporting
software components. software components.
sg_shutdown() performs global finalizations and releases golbally sg_shutdown() performs global finalizations and releases globally
aquired resources. acquired resources.
sg_give_next_adr() iterates over the set of potentially useful drive sg_give_next_adr() iterates over the set of potentially useful drive
address strings. address strings.
@ -57,10 +57,10 @@ scsi_enumerate_drives() brings all available, not-whitelist-banned, and
accessible drives into libburn's list of drives. accessible drives into libburn's list of drives.
sg_dispose_drive() finalizes adapter specifics of struct burn_drive sg_dispose_drive() finalizes adapter specifics of struct burn_drive
on destruction. Releases resources which were aquired on destruction. Releases resources which were acquired
underneath scsi_enumerate_drives(). underneath scsi_enumerate_drives().
sg_drive_is_open() tells wether libburn has the given drive in use. sg_drive_is_open() tells whether libburn has the given drive in use.
sg_grab() opens the drive for SCSI commands and ensures sg_grab() opens the drive for SCSI commands and ensures
undisturbed access. undisturbed access.
@ -68,7 +68,7 @@ sg_grab() opens the drive for SCSI commands and ensures
sg_release() closes a drive opened by sg_grab() sg_release() closes a drive opened by sg_grab()
sg_issue_command() sends a SCSI command to the drive, receives reply, sg_issue_command() sends a SCSI command to the drive, receives reply,
and evaluates wether the command succeeded or shall and evaluates whether the command succeeded or shall
be retried or finally failed. be retried or finally failed.
sg_obtain_scsi_adr() tries to obtain SCSI address parameters. sg_obtain_scsi_adr() tries to obtain SCSI address parameters.
@ -307,7 +307,7 @@ int sg_initialize(char msg[1024], int flag)
/** Performs global finalization of the SCSI transport adapter and eventually /** Performs global finalization of the SCSI transport adapter and eventually
needed operating system facilities. Releases globally aquired resources. needed operating system facilities. Releases globally acquired resources.
@param flag unused yet, submit 0 @param flag unused yet, submit 0
@return 1 = success, <=0 = failure @return 1 = success, <=0 = failure
*/ */
@ -444,7 +444,7 @@ int scsi_enumerate_drives(void)
} }
/** Tells wether libburn has the given drive in use or exclusively reserved. /** 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 If it is "open" then libburn will eventually call sg_release() on it when
it is time to give up usage and reservation. it is time to give up usage and reservation.
*/ */
@ -485,7 +485,7 @@ int sg_grab(struct burn_drive *d)
} }
/** PORTING: Is mainly about the call to sg_close_drive() and wether it /** PORTING: Is mainly about the call to sg_close_drive() and whether it
implements the demanded functionality. implements the demanded functionality.
*/ */
/** Gives up the drive for SCSI commands and releases eventual access locks. /** Gives up the drive for SCSI commands and releases eventual access locks.
@ -500,7 +500,7 @@ int sg_release(struct burn_drive *d)
} }
/** Sends a SCSI command to the drive, receives reply and evaluates wether /** Sends a SCSI command to the drive, receives reply and evaluates whether
the command succeeded or shall be retried or finally failed. the command succeeded or shall be retried or finally failed.
Returned SCSI errors shall not lead to a return value indicating failure. Returned SCSI errors shall not lead to a return value indicating failure.
The callers get notified by c->error. An SCSI failure which leads not to The callers get notified by c->error. An SCSI failure which leads not to
@ -647,7 +647,7 @@ int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
} }
/** Tells wether a text is a persistent address as listed by the enumeration /** Tells whether a text is a persistent address as listed by the enumeration
functions. functions.
*/ */
int sg_is_enumerable_adr(char* adr) int sg_is_enumerable_adr(char* adr)

View File

@ -44,7 +44,7 @@ sg_initialize() performs global initialization of the SCSI transport
facilities. Checks for compatibility of supporting facilities. Checks for compatibility of supporting
software components. software components.
sg_shutdown() performs global finalizations and releases golbally sg_shutdown() performs global finalizations and releases globally
acquired resources. acquired resources.
sg_give_next_adr() iterates over the set of potentially useful drive sg_give_next_adr() iterates over the set of potentially useful drive
@ -57,7 +57,7 @@ sg_dispose_drive() finalizes adapter specifics of struct burn_drive
on destruction. Releases resources which were acquired on destruction. Releases resources which were acquired
underneath scsi_enumerate_drives(). underneath scsi_enumerate_drives().
sg_drive_is_open() tells wether libburn has the given drive in use. sg_drive_is_open() tells whether libburn has the given drive in use.
sg_grab() opens the drive for SCSI commands and ensures sg_grab() opens the drive for SCSI commands and ensures
undisturbed access. undisturbed access.
@ -65,7 +65,7 @@ sg_grab() opens the drive for SCSI commands and ensures
sg_release() closes a drive opened by sg_grab() sg_release() closes a drive opened by sg_grab()
sg_issue_command() sends a SCSI command to the drive, receives reply, sg_issue_command() sends a SCSI command to the drive, receives reply,
and evaluates wether the command succeeded or shall and evaluates whether the command succeeded or shall
be retried or finally failed. be retried or finally failed.
sg_obtain_scsi_adr() tries to obtain SCSI address parameters. sg_obtain_scsi_adr() tries to obtain SCSI address parameters.
@ -609,7 +609,7 @@ int sg_release(struct burn_drive *d)
} }
/** Sends a SCSI command to the drive, receives reply and evaluates wether /** Sends a SCSI command to the drive, receives reply and evaluates whether
the command succeeded or shall be retried or finally failed. the command succeeded or shall be retried or finally failed.
Returned SCSI errors shall not lead to a return value indicating failure. Returned SCSI errors shall not lead to a return value indicating failure.
The callers get notified by c->error. An SCSI failure which leads not to The callers get notified by c->error. An SCSI failure which leads not to
@ -768,7 +768,7 @@ int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
} }
/** Tells wether a text is a persistent address as listed by the enumeration /** Tells whether a text is a persistent address as listed by the enumeration
functions. functions.
*/ */
int sg_is_enumerable_adr(char* adr) int sg_is_enumerable_adr(char* adr)

View File

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2019 Thomas Schmitt <scdbackup@gmx.net> Copyright (c) 2006 - 2020 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later. Provided under GPL version 2 or later.
*/ */
@ -50,7 +50,7 @@ sg_initialize() performs global initialization of the SCSI transport
facilities. Checks for compatibility of supporting facilities. Checks for compatibility of supporting
software components. software components.
sg_shutdown() performs global finalizations and releases golbally sg_shutdown() performs global finalizations and releases globally
acquired resources. acquired resources.
sg_give_next_adr() iterates over the set of potentially useful drive sg_give_next_adr() iterates over the set of potentially useful drive
@ -63,7 +63,7 @@ sg_dispose_drive() finalizes adapter specifics of struct burn_drive
on destruction. Releases resources which were acquired on destruction. Releases resources which were acquired
underneath scsi_enumerate_drives(). underneath scsi_enumerate_drives().
sg_drive_is_open() tells wether libburn has the given drive in use. sg_drive_is_open() tells whether libburn has the given drive in use.
sg_grab() opens the drive for SCSI commands and ensures sg_grab() opens the drive for SCSI commands and ensures
undisturbed access. undisturbed access.
@ -71,7 +71,7 @@ sg_grab() opens the drive for SCSI commands and ensures
sg_release() closes a drive opened by sg_grab() sg_release() closes a drive opened by sg_grab()
sg_issue_command() sends a SCSI command to the drive, receives reply, sg_issue_command() sends a SCSI command to the drive, receives reply,
and evaluates wether the command succeeded or shall and evaluates whether the command succeeded or shall
be retried or finally failed. be retried or finally failed.
sg_obtain_scsi_adr() tries to obtain SCSI address parameters. sg_obtain_scsi_adr() tries to obtain SCSI address parameters.
@ -111,6 +111,15 @@ Hint: You should also look into sg-freebsd-port.c, which is a younger and
/** PORTING : ------- OS dependent headers and definitions ------ */ /** PORTING : ------- OS dependent headers and definitions ------ */
#ifdef Libburn_read_o_direcT
/* ts B91124:
DISABLED, because this spoils multi-track burning of cdrskin by a hard to
fix bug in cdrskin/cdrfifo.c
DO NOT ENABLE before the wait code in that source file is fixed.
*/
#undef Libburn_read_o_direcT
#endif
#ifdef Libburn_read_o_direcT #ifdef Libburn_read_o_direcT
# ifndef _GNU_SOURCE # ifndef _GNU_SOURCE
@ -216,7 +225,7 @@ static char linux_ata_device_family[80] = {"/dev/hd%c"};
/* Set this to 1 in order to get on stderr messages from ata_enumerate() /* Set this to 1 in order to get on stderr messages from ata_enumerate()
*/ */
static int linux_ata_enumerate_verbous = 0; static int linux_ata_enumerate_verbose = 0;
/** PORTING : ------ libburn portable headers and definitions ----- */ /** PORTING : ------ libburn portable headers and definitions ----- */
@ -287,7 +296,7 @@ int mmc_function_spy(struct burn_drive *d, char * text);
/* ------------------------------------------------------------------------ */ /* ------------------------------------------------------------------------ */
/* ts A70413 */ /* ts A70413 */
/* This finds out wether the software is running on kernel >= 2.6 /* This finds out whether the software is running on kernel >= 2.6
*/ */
static void sg_evaluate_kernel(void) static void sg_evaluate_kernel(void)
{ {
@ -305,7 +314,7 @@ static void sg_evaluate_kernel(void)
/* ts A70314 */ /* ts A70314 */
/* This installs the device file family if one was chosen explicitely /* This installs the device file family if one was chosen explicitly
by burn_preset_device_open() by burn_preset_device_open()
*/ */
static void sg_select_device_family(void) static void sg_select_device_family(void)
@ -374,11 +383,16 @@ static int sg_exchange_scd_for_sr(char *fname, int flag)
/* This is an early stage version of scsi_log_cmd. /* This is an early stage version of scsi_log_cmd.
>>> It will become obsolete when the /tmp file handler is moved into >>> It will become obsolete when the /tmp file handler is moved into
>>> scsi_log_command(). >>> scsi_log_command().
@param flag bit0= data direction is FROM_DRIVE
*/ */
static int sgio_log_cmd(unsigned char *cmd, int cmd_len, FILE *fp_in, int flag) static int sgio_log_cmd(unsigned char *cmd, int cmd_len, FILE *fp_in, int flag)
{ {
FILE *fp = fp_in; FILE *fp = fp_in;
int ret = 0; int ret = 0;
int data_dir = NO_TRANSFER;
if (flag & 1)
data_dir = FROM_DRIVE;
/* >>> ts B11110 : move this into scsi_log_command() */ /* >>> ts B11110 : move this into scsi_log_command() */
if (fp == NULL && (burn_sg_log_scsi & 1)) { if (fp == NULL && (burn_sg_log_scsi & 1)) {
@ -389,10 +403,13 @@ static int sgio_log_cmd(unsigned char *cmd, int cmd_len, FILE *fp_in, int flag)
} }
if (fp != NULL) if (fp != NULL)
ret = scsi_log_command(cmd, cmd_len, NO_TRANSFER, NULL, 0, ret = scsi_log_command(cmd, cmd_len, data_dir, NULL, 0,
fp, flag); fp, flag);
if (fp_in == NULL && fp != NULL) if (fp_in == NULL && fp != NULL)
fclose(fp); fclose(fp);
if (fp == stderr || !(burn_sg_log_scsi & 2))
return ret;
ret = scsi_log_command(cmd, cmd_len, data_dir, NULL, 0, stderr, 0);
return ret; return ret;
} }
@ -464,7 +481,7 @@ static int sgio_inquiry_cd_drive(int fd, char *fname)
s.dxfer_len = 36; s.dxfer_len = 36;
s.usr_ptr = NULL; s.usr_ptr = NULL;
sgio_log_cmd(s.cmdp, s.cmd_len, NULL, 0); sgio_log_cmd(s.cmdp, s.cmd_len, NULL, 1);
c_start_time = burn_get_time(0); c_start_time = burn_get_time(0);
ret = ioctl(fd, SG_IO, &s); ret = ioctl(fd, SG_IO, &s);
@ -650,7 +667,7 @@ ex:;
So libburn will by default use open(O_EXCL) first and afterwards So libburn will by default use open(O_EXCL) first and afterwards
as second assertion will use fcntl(F_SETLK). One lock more should not harm. as second assertion will use fcntl(F_SETLK). One lock more should not harm.
*/ */
static int sg_fcntl_lock(int *fd, char *fd_name, int l_type, int verbous) static int sg_fcntl_lock(int *fd, char *fd_name, int l_type, int verbose)
{ {
struct flock lockthing; struct flock lockthing;
char msg[81]; char msg[81];
@ -671,7 +688,7 @@ static int sg_fcntl_lock(int *fd, char *fd_name, int l_type, int verbous)
ret = fcntl(*fd, F_SETLK, &lockthing); ret = fcntl(*fd, F_SETLK, &lockthing);
if (ret == -1) { if (ret == -1) {
if (verbous) { if (verbose) {
sprintf(msg, "Device busy. Failed to fcntl-lock '%s'", sprintf(msg, "Device busy. Failed to fcntl-lock '%s'",
fd_name); fd_name);
libdax_msgs_submit(libdax_messenger, -1, 0x00020008, libdax_msgs_submit(libdax_messenger, -1, 0x00020008,
@ -803,6 +820,88 @@ static int sg_release_siblings(int sibling_fds[],
} }
/* ts C00806 */
/** Urges the operating system to re-assess drive and medium state
*/
static int sg_os_revalidate_disc(struct burn_drive *d)
{
#ifdef Libburn_use_linux_ioctl_simul_changE
/* <<< only for compiler tests */
#ifndef CDROM_SIMUL_CHANGE
/* # def ine CDROM_SIMUL_CHANGE 0x5332 */
#endif
#ifdef CDROM_SIMUL_CHANGE
int fd, ret;
long old_blocks, new_blocks;
char *msg = NULL;
BURN_ALLOC_MEM(msg, char, 161);
ret = ioctl(d->fd, BLKGETSIZE, &old_blocks);
if (ret == -1)
old_blocks = -1;
/* Schedule a simulated medium change event.
Although the implemented ioctl cannot fail, the kernel might be too
old to know it and then throw errors like ENOTTY.
*/
ret = ioctl(d->fd, CDROM_SIMUL_CHANGE, 0);
if (ret == -1) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x02, LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
"ioctl(CDROM_SIMUL_CHANGE) failed", errno, 0);
ret = 0; goto ex;
}
libdax_msgs_submit(libdax_messenger, d->global_index,
0x02, LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
"ioctl(CDROM_SIMUL_CHANGE) was performed", 0, 0);
/* Try to trigger actual device assessment by a open(2) call */
fd = open(d->devname, O_RDONLY | O_NDELAY);
if (fd == -1) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x02, LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
"Failed to open device file after ioctl(CDROM_SIMUL_CHANGE)",
errno, 0);
ret = 0; goto ex;
}
close(fd);
ret = ioctl(d->fd, BLKGETSIZE, &new_blocks);
if (ret == -1) {
libdax_msgs_submit(libdax_messenger, d->global_index,
0x02, LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
"BLKGETSIZE failed after ioctl(CDROM_SIMUL_CHANGE)",
errno, 0);
} else if (old_blocks != new_blocks) {
sprintf(msg,
"BLKGETSIZE indicates size change from %ld to %ld blocks",
old_blocks , new_blocks);
libdax_msgs_submit(libdax_messenger, d->global_index,
0x02, LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
}
ex:
BURN_FREE_MEM(msg);
return ret;
#else /* CDROM_SIMUL_CHANGE */
return 0;
#endif /* ! CDROM_SIMUL_CHANGE */
#else /* Libburn_use_linux_ioctl_simul_changE */
return 0;
#endif /* ! Libburn_use_linux_ioctl_simul_changE */
}
/* ts A60926 */ /* ts A60926 */
static int sg_close_drive(struct burn_drive *d) static int sg_close_drive(struct burn_drive *d)
{ {
@ -812,6 +911,9 @@ static int sg_close_drive(struct burn_drive *d)
return 0; return 0;
sg_release_siblings(d->sibling_fds, d->sibling_fnames, sg_release_siblings(d->sibling_fds, d->sibling_fnames,
&(d->sibling_count)); &(d->sibling_count));
if(d->medium_state_changed > 0)
sg_os_revalidate_disc(d);
d->medium_state_changed = -1;
ret = sg_close_drive_fd(d->devname, d->global_index, &(d->fd), 0); ret = sg_close_drive_fd(d->devname, d->global_index, &(d->fd), 0);
return ret; return ret;
} }
@ -919,7 +1021,7 @@ static int is_ata_drive(char *fname, int fd_in)
else else
fd = sg_open_drive_fd(fname, 1); fd = sg_open_drive_fd(fname, 1);
if (fd == -1) { if (fd == -1) {
if (linux_ata_enumerate_verbous) if (linux_ata_enumerate_verbose)
fprintf(stderr,"open failed, errno=%d '%s'\n", fprintf(stderr,"open failed, errno=%d '%s'\n",
errno, strerror(errno)); errno, strerror(errno));
return 0; return 0;
@ -930,7 +1032,7 @@ static int is_ata_drive(char *fname, int fd_in)
/* not atapi */ /* not atapi */
if (!(tm.config & 0x8000) || (tm.config & 0x4000)) { if (!(tm.config & 0x8000) || (tm.config & 0x4000)) {
if (linux_ata_enumerate_verbous) if (linux_ata_enumerate_verbose)
fprintf(stderr, "not marked as ATAPI\n"); fprintf(stderr, "not marked as ATAPI\n");
if (fd_in < 0) if (fd_in < 0)
sg_close_drive_fd(fname, -1, &fd, 0); sg_close_drive_fd(fname, -1, &fd, 0);
@ -940,7 +1042,7 @@ static int is_ata_drive(char *fname, int fd_in)
/* if SG_IO fails on an atapi device, we should stop trying to /* if SG_IO fails on an atapi device, we should stop trying to
use hd* devices */ use hd* devices */
if (sgio_test(fd) == -1) { if (sgio_test(fd) == -1) {
if (linux_ata_enumerate_verbous) if (linux_ata_enumerate_verbose)
fprintf(stderr, fprintf(stderr,
"FATAL: sgio_test() failed: errno=%d '%s'\n", "FATAL: sgio_test() failed: errno=%d '%s'\n",
errno, strerror(errno)); errno, strerror(errno));
@ -951,7 +1053,7 @@ static int is_ata_drive(char *fname, int fd_in)
if (fd_in >= 0) if (fd_in >= 0)
return 1; return 1;
if (sg_close_drive_fd(fname, -1, &fd, 1) <= 0) { if (sg_close_drive_fd(fname, -1, &fd, 1) <= 0) {
if (linux_ata_enumerate_verbous) if (linux_ata_enumerate_verbose)
fprintf(stderr, fprintf(stderr,
"cannot close properly, errno=%d '%s'\n", "cannot close properly, errno=%d '%s'\n",
errno, strerror(errno)); errno, strerror(errno));
@ -1097,7 +1199,7 @@ static int sg_open_for_enumeration(char *fname, int flag)
fd = sg_open_drive_fd(fname, 1 + (flag & 1)); fd = sg_open_drive_fd(fname, 1 + (flag & 1));
if (fd < 0) { if (fd < 0) {
if (linux_sg_enumerate_debug || linux_ata_enumerate_verbous) if (linux_sg_enumerate_debug || linux_ata_enumerate_verbose)
fprintf(stderr, "open failed, errno=%d '%s'\n", fprintf(stderr, "open failed, errno=%d '%s'\n",
errno, strerror(errno)); errno, strerror(errno));
return -1; return -1;
@ -1113,7 +1215,7 @@ static void ata_enumerate(void)
int ret, i, fd = -1; int ret, i, fd = -1;
char fname[10]; char fname[10];
if (linux_ata_enumerate_verbous) if (linux_ata_enumerate_verbose)
fprintf(stderr, "libburn_debug: linux_ata_device_family = %s\n", fprintf(stderr, "libburn_debug: linux_ata_device_family = %s\n",
linux_ata_device_family); linux_ata_device_family);
@ -1122,12 +1224,12 @@ static void ata_enumerate(void)
for (i = 0; i < 26; i++) { for (i = 0; i < 26; i++) {
sprintf(fname, linux_ata_device_family, 'a' + i); sprintf(fname, linux_ata_device_family, 'a' + i);
if (linux_ata_enumerate_verbous) if (linux_ata_enumerate_verbose)
fprintf(stderr, "libburn_debug: %s : ", fname); fprintf(stderr, "libburn_debug: %s : ", fname);
/* ts A51221 */ /* ts A51221 */
if (burn_drive_is_banned(fname)) { if (burn_drive_is_banned(fname)) {
if (linux_ata_enumerate_verbous) if (linux_ata_enumerate_verbose)
fprintf(stderr, "not in whitelist\n"); fprintf(stderr, "not in whitelist\n");
continue; continue;
} }
@ -1139,7 +1241,7 @@ static void ata_enumerate(void)
break; break;
if (ret == 0) if (ret == 0)
continue; continue;
if (linux_ata_enumerate_verbous) if (linux_ata_enumerate_verbose)
fprintf(stderr, "accepting as drive without SCSI address\n"); fprintf(stderr, "accepting as drive without SCSI address\n");
enumerate_common(fname, fd, -1, -1, -1, -1, -1); enumerate_common(fname, fd, -1, -1, -1, -1, -1);
} }
@ -1667,7 +1769,7 @@ int scsi_enumerate_drives(void)
} }
/** Tells wether libburn has the given drive in use or exclusively reserved. /** 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 If it is "open" then libburn will eventually call sg_release() on it when
it is time to give up usage and reservation. it is time to give up usage and reservation.
*/ */
@ -1722,7 +1824,7 @@ int sg_grab(struct burn_drive *d)
/* ts A60813 - A60822 /* ts A60813 - A60822
After enumeration the drive fd is probably still open. After enumeration the drive fd is probably still open.
-1337 is the initial value of burn_drive.fd and the value after -1337 is the initial value of burn_drive.fd and the value after
relase of drive. Unclear why not the official error return release of drive. Unclear why not the official error return
value -1 of open(2) war used. */ value -1 of open(2) war used. */
if(! burn_drive_is_open(d)) { if(! burn_drive_is_open(d)) {
char msg[120]; char msg[120];
@ -1847,7 +1949,7 @@ drive_is_in_use:;
} }
/** PORTING: Is mainly about the call to sg_close_drive() and wether it /** PORTING: Is mainly about the call to sg_close_drive() and whether it
implements the demanded functionality. implements the demanded functionality.
*/ */
/** Gives up the drive for SCSI commands and releases eventual access locks. /** Gives up the drive for SCSI commands and releases eventual access locks.
@ -2045,7 +2147,7 @@ static void react_on_drive_loss(struct burn_drive *d, struct command *c,
scsi_log_message(d, fp, "--- SG_IO: Gave up connection to drive", 0); scsi_log_message(d, fp, "--- SG_IO: Gave up connection to drive", 0);
} }
/** Sends a SCSI command to the drive, receives reply and evaluates wether /** Sends a SCSI command to the drive, receives reply and evaluates whether
the command succeeded or shall be retried or finally failed. the command succeeded or shall be retried or finally failed.
Returned SCSI errors shall not lead to a return value indicating failure. Returned SCSI errors shall not lead to a return value indicating failure.
The callers get notified by c->error. An SCSI failure which leads not to The callers get notified by c->error. An SCSI failure which leads not to
@ -2276,7 +2378,7 @@ static int sg_obtain_scsi_adr_fd(char *path, int fd_in,
}; };
struct my_scsi_idlun idlun; struct my_scsi_idlun idlun;
/* valgrind called idlun unitialized because it is blind for ioctl */ /* valgrind called idlun uninitialized because it is blind for ioctl */
idlun.x = 0; idlun.x = 0;
idlun.host_unique_id = 0; idlun.host_unique_id = 0;
@ -2345,7 +2447,7 @@ int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
/* ts A60922 ticket 33 : called from drive.c */ /* ts A60922 ticket 33 : called from drive.c */
/** Tells wether a text is a persistent address as listed by the enumeration /** Tells whether a text is a persistent address as listed by the enumeration
functions. functions.
*/ */
int sg_is_enumerable_adr(char *adr) int sg_is_enumerable_adr(char *adr)

View File

@ -51,7 +51,7 @@ sg_initialize() performs global initialization of the SCSI transport
facilities. Checks for compatibility of supporting facilities. Checks for compatibility of supporting
software components. software components.
sg_shutdown() performs global finalizations and releases golbally sg_shutdown() performs global finalizations and releases globally
acquired resources. acquired resources.
sg_give_next_adr() iterates over the set of potentially useful drive sg_give_next_adr() iterates over the set of potentially useful drive
@ -64,7 +64,7 @@ sg_dispose_drive() finalizes adapter specifics of struct burn_drive
on destruction. Releases resources which were acquired on destruction. Releases resources which were acquired
underneath scsi_enumerate_drives(). underneath scsi_enumerate_drives().
sg_drive_is_open() tells wether libburn has the given drive in use. sg_drive_is_open() tells whether libburn has the given drive in use.
sg_grab() opens the drive for SCSI commands and ensures sg_grab() opens the drive for SCSI commands and ensures
undisturbed access. undisturbed access.
@ -72,7 +72,7 @@ sg_grab() opens the drive for SCSI commands and ensures
sg_release() closes a drive opened by sg_grab() sg_release() closes a drive opened by sg_grab()
sg_issue_command() sends a SCSI command to the drive, receives reply, sg_issue_command() sends a SCSI command to the drive, receives reply,
and evaluates wether the command succeeded or shall and evaluates whether the command succeeded or shall
be retried or finally failed. be retried or finally failed.
sg_obtain_scsi_adr() tries to obtain SCSI address parameters. sg_obtain_scsi_adr() tries to obtain SCSI address parameters.
@ -525,7 +525,7 @@ int sg_release(struct burn_drive *d)
} }
/** Sends a SCSI command to the drive, receives reply and evaluates wether /** Sends a SCSI command to the drive, receives reply and evaluates whether
the command succeeded or shall be retried or finally failed. the command succeeded or shall be retried or finally failed.
Returned SCSI errors shall not lead to a return value indicating failure. Returned SCSI errors shall not lead to a return value indicating failure.
The callers get notified by c->error. An SCSI failure which leads not to The callers get notified by c->error. An SCSI failure which leads not to
@ -721,7 +721,7 @@ ex:;
} }
/** Tells wether a text is a persistent address as listed by the enumeration /** Tells whether a text is a persistent address as listed by the enumeration
functions. functions.
*/ */
int sg_is_enumerable_adr(char* adr) int sg_is_enumerable_adr(char* adr)

View File

@ -44,7 +44,7 @@ sg_initialize() performs global initialization of the SCSI transport
facilities. Checks for compatibility of supporting facilities. Checks for compatibility of supporting
software components. software components.
sg_shutdown() performs global finalizations and releases golbally sg_shutdown() performs global finalizations and releases globally
acquired resources. acquired resources.
sg_give_next_adr() iterates over the set of potentially useful drive sg_give_next_adr() iterates over the set of potentially useful drive
@ -57,7 +57,7 @@ sg_dispose_drive() finalizes adapter specifics of struct burn_drive
on destruction. Releases resources which were acquired on destruction. Releases resources which were acquired
underneath scsi_enumerate_drives(). underneath scsi_enumerate_drives().
sg_drive_is_open() tells wether libburn has the given drive in use. sg_drive_is_open() tells whether libburn has the given drive in use.
sg_grab() opens the drive for SCSI commands and ensures sg_grab() opens the drive for SCSI commands and ensures
undisturbed access. undisturbed access.
@ -65,7 +65,7 @@ sg_grab() opens the drive for SCSI commands and ensures
sg_release() closes a drive opened by sg_grab() sg_release() closes a drive opened by sg_grab()
sg_issue_command() sends a SCSI command to the drive, receives reply, sg_issue_command() sends a SCSI command to the drive, receives reply,
and evaluates wether the command succeeded or shall and evaluates whether the command succeeded or shall
be retried or finally failed. be retried or finally failed.
sg_obtain_scsi_adr() tries to obtain SCSI address parameters. sg_obtain_scsi_adr() tries to obtain SCSI address parameters.
@ -690,7 +690,7 @@ int sg_release(struct burn_drive *d)
} }
/** Sends a SCSI command to the drive, receives reply and evaluates wether /** Sends a SCSI command to the drive, receives reply and evaluates whether
the command succeeded or shall be retried or finally failed. the command succeeded or shall be retried or finally failed.
Returned SCSI errors shall not lead to a return value indicating failure. Returned SCSI errors shall not lead to a return value indicating failure.
The callers get notified by c->error. An SCSI failure which leads not to The callers get notified by c->error. An SCSI failure which leads not to
@ -837,7 +837,7 @@ int sg_obtain_scsi_adr(char *path, int *bus_no, int *host_no, int *channel_no,
} }
/** Tells wether a text is a persistent address as listed by the enumeration /** Tells whether a text is a persistent address as listed by the enumeration
functions. functions.
*/ */

View File

@ -195,8 +195,8 @@ int spc_wait_unit_attention(struct burn_drive *d, int max_sec, char *cmd_text,
*/ */
break; break;
} }
if (key == 0x6 && asc == 0x28 && ascq == 0x00) if (key == 0x6 && asc == 0x28)
/* media change notice = try again */ /* medium change notice or alike = try again */
goto slumber; goto slumber;
handle_error:; handle_error:;
@ -1056,7 +1056,7 @@ void spc_probe_write_modes(struct burn_drive *d)
struct buffer *buf = NULL; struct buffer *buf = NULL;
int try_write_type = 1; int try_write_type = 1;
int try_block_type = 0; int try_block_type = 0;
int key, asc, ascq, useable_write_type = -1, useable_block_type = -1; int key, asc, ascq, usable_write_type = -1, usable_block_type = -1;
int last_try = 0; int last_try = 0;
struct command *c = NULL; struct command *c = NULL;
@ -1071,11 +1071,11 @@ void spc_probe_write_modes(struct burn_drive *d)
while (try_write_type != 5) { while (try_write_type != 5) {
/* ts A70213 */ /* ts A70213 */
if (try_write_type == 4) { if (try_write_type == 4) {
/* Pseudo write type NONE . Set a useable write mode */ /* Pseudo write type NONE . Set a usable write mode */
if (useable_write_type == -1) if (usable_write_type == -1)
break; break;
try_write_type = useable_write_type; try_write_type = usable_write_type;
try_block_type = useable_block_type; try_block_type = usable_block_type;
last_try= 1; last_try= 1;
} }
@ -1118,12 +1118,12 @@ void spc_probe_write_modes(struct burn_drive *d)
1 << try_block_type; 1 << try_block_type;
/* ts A70213 */ /* ts A70213 */
if ((useable_write_type < 0 && try_write_type > 0) || if ((usable_write_type < 0 && try_write_type > 0) ||
(try_write_type == 1 && try_block_type == 8)) { (try_write_type == 1 && try_block_type == 8)) {
/* Packet is not supported yet. /* Packet is not supported yet.
Prefer TAO MODE_1. */ Prefer TAO MODE_1. */
useable_write_type = try_write_type; usable_write_type = try_write_type;
useable_block_type = try_block_type; usable_block_type = try_block_type;
} }
} }
switch (try_block_type) { switch (try_block_type) {
@ -1446,8 +1446,15 @@ enum response scsi_error_msg(struct burn_drive *d, unsigned char *sense,
case 0x28: case 0x28:
if (*ascq == 0) if (*ascq == 0)
sprintf(msg, "Medium may have changed"); sprintf(msg, "Medium may have changed");
else if (*ascq == 1)
sprintf(msg, "Import or export element accessed");
else if (*ascq == 2) else if (*ascq == 2)
sprintf(msg, "Format layer may have changed"); sprintf(msg, "Format layer may have changed");
else if (*ascq == 3)
sprintf(msg,
"Import/export element accessed, medium changed");
else if (*key == 6)
sprintf(msg, "Unknown ASCQ with drive event ASC 28");
else else
break; break;
goto return_retry; goto return_retry;

View File

@ -1,6 +1,6 @@
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2014 Thomas Schmitt <scdbackup@gmx.net> Copyright (c) 2006 - 2021 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later. Provided under GPL version 2 or later.
*/ */
@ -34,6 +34,7 @@
#include "util.h" #include "util.h"
#include "transport.h" #include "transport.h"
#include "mmc.h" #include "mmc.h"
#include "drive.h"
#include "libdax_msgs.h" #include "libdax_msgs.h"
extern struct libdax_msgs *libdax_messenger; extern struct libdax_msgs *libdax_messenger;
@ -319,8 +320,8 @@ void burn_structure_print_track(struct burn_track *t)
{ {
char msg[80]; char msg[80];
sprintf(msg, " track size %d sectors", sprintf(msg, " track size %.f sectors",
burn_track_get_sectors(t)); (double) burn_track_get_sectors_v2(t));
libdax_msgs_submit(libdax_messenger, -1, 0x00000002, libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH, LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0); msg, 0, 0);
@ -506,14 +507,14 @@ int burn_track_set_postgap_size(struct burn_track *t, int size, int flag)
return 1; return 1;
} }
/* ts B20119: outsourced from burn_track_get_sectors() /* ts B20119 / C40302: outsourced from burn_track_get_sectors()
@param flag bit0= do not add post-gap @param flag bit0= do not add post-gap
*/ */
int burn_track_get_sectors_2(struct burn_track *t, int flag) off_t burn_track_get_sectors_2_v2(struct burn_track *t, int flag)
{ {
/* ts A70125 : was int */ /* ts A70125 : was int */
off_t size = 0; off_t size = 0, sectors;
int sectors, seclen; int seclen;
seclen = burn_sector_length(t->mode); seclen = burn_sector_length(t->mode);
@ -529,9 +530,23 @@ int burn_track_get_sectors_2(struct burn_track *t, int flag)
} else if(t->entry != NULL) { } else if(t->entry != NULL) {
/* ts A80808 : all burn_toc_entry of track starts should now /* ts A80808 : all burn_toc_entry of track starts should now
have (extensions_valid & 1), even those from CD. have (extensions_valid & 1), even those from CD.
ts C40302 : Now there should be long_track_blocks.
*/ */
if (t->entry->extensions_valid & 1) if (t->entry->extensions_valid & 8) {
size = t->entry->long_track_blocks * (off_t) 2048;
} else if (t->entry->extensions_valid & 1) {
size = ((off_t) t->entry->track_blocks) * (off_t) 2048; size = ((off_t) t->entry->track_blocks) * (off_t) 2048;
}
}
if (size > BURN_DRIVE_MAX_BYTES) {
char msg[80];
sprintf(msg, "Track size exceeds limit of %.f bytes",
(double) (BURN_DRIVE_MAX_BYTES));
libdax_msgs_submit(libdax_messenger, -1, 0x000201ae,
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
return -1;
} }
sectors = size / seclen; sectors = size / seclen;
if (size % seclen) if (size % seclen)
@ -539,14 +554,34 @@ int burn_track_get_sectors_2(struct burn_track *t, int flag)
return sectors; return sectors;
} }
int burn_track_get_sectors_2(struct burn_track *t, int flag)
{
/* ts A70125 : was int */
off_t sectors = 0;
sectors = burn_track_get_sectors_2_v2(t, flag);
if (sectors > (off_t) 0x7ffffff0) {
libdax_msgs_submit(libdax_messenger, -1, 0x000201ae,
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
"Track size exceeds 4 TiB - 32 KiB", 0, 0);
return -1;
}
return (int) sectors;
}
int burn_track_get_sectors(struct burn_track *t) int burn_track_get_sectors(struct burn_track *t)
{ {
return burn_track_get_sectors_2(t, 0); return burn_track_get_sectors_2(t, 0);
} }
/* ts C40302 : API */
off_t burn_track_get_sectors_v2(struct burn_track *t)
{
return burn_track_get_sectors_2_v2(t, 0);
}
/* ts A70125 */ /* ts A70125 */
int burn_track_set_sectors(struct burn_track *t, int sectors) int burn_track_set_sectors(struct burn_track *t, off_t sectors)
{ {
off_t size, seclen; off_t size, seclen;
int ret; int ret;
@ -589,17 +624,29 @@ 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) int burn_track_apply_fillup(struct burn_track *t, off_t max_size, int flag)
{ {
int max_sectors, ret = 2; int ret = 2;
off_t max_sectors, track_sectors;
char msg[80]; char msg[80];
if (t->fill_up_media <= 0) if (t->fill_up_media <= 0)
return 2; return 2;
if (max_size > BURN_DRIVE_MAX_BYTES) {
sprintf(msg, "Track size exceeds limit of %.f bytes",
(double) (BURN_DRIVE_MAX_BYTES));
libdax_msgs_submit(libdax_messenger, -1, 0x000201ae,
LIBDAX_MSGS_SEV_FAILURE, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
return 0;
}
max_sectors = max_size / 2048; max_sectors = max_size / 2048;
if (burn_track_get_sectors(t) < max_sectors || (flag & 1)) { track_sectors = burn_track_get_sectors_v2(t);
sprintf(msg, "Setting total track size to %ds (payload %ds)\n", if (track_sectors < 0)
max_sectors & 0x7fffffff, return 0;
(int) ((t->source->get_size(t->source) / 2048) if (track_sectors < max_sectors || (flag & 1)) {
& 0x7fffffff)); sprintf(msg,
"Setting total track size to %.fs (payload %.fs)\n",
(double) max_sectors,
(double) (t->source->get_size(t->source) / 2048));
libdax_msgs_submit(libdax_messenger, -1, 0x00000002, libdax_msgs_submit(libdax_messenger, -1, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO,
msg, 0, 0); msg, 0, 0);
@ -653,7 +700,7 @@ int burn_track_is_data_done(struct burn_track *t)
int burn_track_get_shortage(struct burn_track *t) int burn_track_get_shortage(struct burn_track *t)
{ {
int size; off_t size;
int seclen; int seclen;
seclen = burn_sector_length(t->mode); seclen = burn_sector_length(t->mode);
@ -665,13 +712,31 @@ int burn_track_get_shortage(struct burn_track *t)
int burn_session_get_sectors(struct burn_session *s) int burn_session_get_sectors(struct burn_session *s)
{ {
int sectors = 0, i; int sectors = 0, i, track_sectors;
for (i = 0; i < s->tracks; i++) for (i = 0; i < s->tracks; i++) {
sectors += burn_track_get_sectors(s->track[i]); track_sectors = burn_track_get_sectors(s->track[i]);
if (track_sectors < 0)
track_sectors = 0;
sectors += track_sectors;
}
return sectors; return sectors;
} }
/* ts C40302: API */
off_t burn_session_get_sectors_v2(struct burn_session *s)
{
int i;
off_t sectors = 0, track_sectors;
for (i = 0; i < s->tracks; i++) {
track_sectors = burn_track_get_sectors_v2(s->track[i]);
if (track_sectors < 0)
track_sectors = 0;
sectors += track_sectors;
}
return sectors;
}
int burn_disc_get_sectors(struct burn_disc *d) int burn_disc_get_sectors(struct burn_disc *d)
{ {
@ -682,6 +747,17 @@ int burn_disc_get_sectors(struct burn_disc *d)
return sectors; return sectors;
} }
/* ts C40302: API */
off_t burn_disc_get_sectors_v2(struct burn_disc *d)
{
int i;
off_t sectors = 0;
for (i = 0; i < d->sessions; i++)
sectors += burn_session_get_sectors_v2(d->session[i]);
return sectors;
}
void burn_track_get_entry(struct burn_track *t, struct burn_toc_entry *entry) void burn_track_get_entry(struct burn_track *t, struct burn_toc_entry *entry)
{ {
if (t->entry == NULL) if (t->entry == NULL)
@ -749,7 +825,7 @@ int burn_session_get_hidefirst(struct burn_session *session)
} }
/* ts A80808 : Enhance CD toc to DVD toc */ /* ts A80808,C40226 : Enhance CD toc to DVD toc with Long block addresses */
int burn_disc_cd_toc_extensions(struct burn_drive *drive, int flag) int burn_disc_cd_toc_extensions(struct burn_drive *drive, int flag)
{ {
int sidx= 0, tidx= 0, ret, track_offset, alloc_len = 34; int sidx= 0, tidx= 0, ret, track_offset, alloc_len = 34;
@ -817,6 +893,7 @@ int burn_disc_cd_toc_extensions(struct burn_drive *drive, int flag)
entry->point_msb = 0; entry->point_msb = 0;
entry->start_lba = burn_msf_to_lba(entry->pmin, entry->start_lba = burn_msf_to_lba(entry->pmin,
entry->psec, entry->pframe); entry->psec, entry->pframe);
entry->long_start_lba = entry->start_lba;
if (tidx > 0) { if (tidx > 0) {
prev_entry->track_blocks = prev_entry->track_blocks =
entry->start_lba entry->start_lba
@ -836,13 +913,16 @@ int burn_disc_cd_toc_extensions(struct burn_drive *drive, int flag)
ret < prev_entry->track_blocks - 2)) ret < prev_entry->track_blocks - 2))
prev_entry->track_blocks = ret; prev_entry->track_blocks = ret;
} }
prev_entry->extensions_valid |= 1; prev_entry->long_track_blocks =
prev_entry->track_blocks;
prev_entry->extensions_valid |= 1 | 8;
} }
if (tidx == d->session[sidx]->tracks) { if (tidx == d->session[sidx]->tracks) {
entry->session_msb = 0; entry->session_msb = 0;
entry->point_msb = 0; entry->point_msb = 0;
entry->track_blocks = 0; entry->track_blocks = 0;
entry->extensions_valid |= 1; entry->long_track_blocks = entry->track_blocks;
entry->extensions_valid |= 1 | 8;
} }
prev_entry = entry; prev_entry = entry;
} }

View File

@ -53,7 +53,7 @@ struct burn_track
/** 1 means Pad with zeros, 0 means start reading the next track */ /** 1 means Pad with zeros, 0 means start reading the next track */
int pad; int pad;
/* ts A70213 : wether to expand this track to full available media */ /* ts A70213 : whether to expand this track to full available media */
int fill_up_media; int fill_up_media;
/* ts A70218 : a track size to use if it is mandarory to have some */ /* ts A70218 : a track size to use if it is mandarory to have some */
@ -137,7 +137,7 @@ struct burn_session
unsigned char cdtext_language[8]; unsigned char cdtext_language[8];
/* ts B11226 */ /* ts B11226 */
unsigned char mediacatalog[14]; /* overrideable by burn_write_opts */ unsigned char mediacatalog[14]; /* overridable by burn_write_opts */
}; };
struct burn_disc struct burn_disc
@ -160,7 +160,7 @@ int burn_track_is_open_ended(struct burn_track *t);
int burn_track_is_data_done(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 */ /* ts A70125 : sets overall sectors of a track: offset+payload+padding */
int burn_track_set_sectors(struct burn_track *t, int sectors); int burn_track_set_sectors(struct burn_track *t, off_t sectors);
/* ts A70218 : sets the payload size alone */ /* ts A70218 : sets the payload size alone */
int burn_track_set_size(struct burn_track *t, off_t size); int burn_track_set_size(struct burn_track *t, off_t size);
@ -185,6 +185,7 @@ void burn_cdtext_free(struct burn_cdtext **cdtext);
/* @param flag bit0= do not add post-gap /* @param flag bit0= do not add post-gap
*/ */
int burn_track_get_sectors_2(struct burn_track *t, int flag); int burn_track_get_sectors_2(struct burn_track *t, int flag);
off_t burn_track_get_sectors_2_v2(struct burn_track *t, int flag);
#endif /* BURN__STRUCTURE_H */ #endif /* BURN__STRUCTURE_H */

View File

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2016 Thomas Schmitt <scdbackup@gmx.net> Copyright (c) 2006 - 2024 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later. Provided under GPL version 2 or later.
*/ */
@ -277,7 +277,7 @@ struct burn_drive
(which could need closing after write) */ (which could need closing after write) */
int needs_close_session; int needs_close_session;
/* ts A71003 : whether a random write operation was done and no /* ts A71003 : whether a random write operation was done and no
synchronize chache has happened yet */ synchronize cache has happened yet */
int needs_sync_cache; int needs_sync_cache;
/* ts A80412 : whether to use WRITE12 with Streaming bit set /* ts A80412 : whether to use WRITE12 with Streaming bit set
@ -335,7 +335,7 @@ struct burn_drive
int stdio_fd; int stdio_fd;
int nwa; /* next writeable address */ off_t nwa; /* next writeable address */
int alba; /* absolute lba */ int alba; /* absolute lba */
int rlba; /* relative lba in section */ int rlba; /* relative lba in section */
int start_lba; int start_lba;
@ -371,19 +371,21 @@ struct burn_drive
/* ts A70215 : if > 0 : first lba on media that is too high for write*/ /* ts A70215 : if > 0 : first lba on media that is too high for write*/
int media_lba_limit; int media_lba_limit;
/* ts A81210 : Upper limit of readable data size, /* ts A81210 / C40303 : Upper limit of readable data size,
0x7fffffff = unknown 0x7fffffffffffffff = unknown
0x7ffffff0 = 32 bit overflow, or unknown stdio size BURN_DRIVE_MAX_BYTES / 2048 = possibly truncated
or unknown stdio size
*/ */
int media_read_capacity; off_t media_read_capacity;
/* ts B60305 : Whether READ CAPACITY of CD is credible: /* ts B60305 : Whether READ CAPACITY of CD is credible:
-1= no READ CAPACITY yet , 0= untrusted READ CAPACITY -1= no READ CAPACITY yet , 0= untrusted READ CAPACITY
1= READ CAPACITY confirmed or corrected by other commands 1= READ CAPACITY confirmed or corrected by other commands
*/ */
int mr_capacity_trusted; int mr_capacity_trusted;
/* ts B10314 : Next Writeable Address for drive_role == 5 */ /* ts B10314 / C40302 : Next Writeable Address for drive_role == 5 */
int role_5_nwa; off_t role_5_nwa;
/* ts B60730 */ /* ts B60730 */
int do_no_immed; int do_no_immed;
@ -392,7 +394,7 @@ struct burn_drive
struct burn_disc *disc; /* disc structure */ struct burn_disc *disc; /* disc structure */
int block_types[4]; int block_types[4];
struct buffer *buffer; struct buffer *buffer;
struct burn_progress progress; struct burn_progress_v2 progress;
/* To be used by mmc.c, sbc.c, spc.c for SCSI commands where the struct /* 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 content surely does not have to persist while another command gets
@ -438,6 +440,17 @@ struct burn_drive
/* ts B90513 */ /* ts B90513 */
unsigned int write_retry_count; unsigned int write_retry_count;
/* ts C00806 */
/* 0=no change, 1=change, -1=already urged OS to revalidate medium */
int medium_state_changed;
/* ts C00822 */
/* If set, use Exact bit with SET STREAMING and use SET STREAMING
even if the medium is a CD.
*/
int set_streaming_exact_bit;
int set_streaming_err;
/* transport functions */ /* transport functions */
int (*grab) (struct burn_drive *); int (*grab) (struct burn_drive *);
int (*release) (struct burn_drive *); int (*release) (struct burn_drive *);
@ -454,7 +467,7 @@ struct burn_drive
/* ts A61021 */ /* ts A61021 */
void (*read_atip) (struct burn_drive *); void (*read_atip) (struct burn_drive *);
int (*write) (struct burn_drive *, int, struct buffer *); int (*write) (struct burn_drive *, off_t, struct buffer *);
void (*read_toc) (struct burn_drive *); void (*read_toc) (struct burn_drive *);
void (*lock) (struct burn_drive *); void (*lock) (struct burn_drive *);
void (*unlock) (struct burn_drive *); void (*unlock) (struct burn_drive *);

View File

@ -1,7 +1,7 @@
/* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */ /* -*- indent-tabs-mode: t; tab-width: 8; c-basic-offset: 8; -*- */
/* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens /* Copyright (c) 2004 - 2006 Derek Foreman, Ben Jansens
Copyright (c) 2006 - 2017 Thomas Schmitt <scdbackup@gmx.net> Copyright (c) 2006 - 2024 Thomas Schmitt <scdbackup@gmx.net>
Provided under GPL version 2 or later. Provided under GPL version 2 or later.
*/ */
@ -630,11 +630,13 @@ struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o,
track length. track length.
*/ */
track_length = burn_track_get_sectors_2(tar[i], 1); track_length = burn_track_get_sectors_2(tar[i], 1);
if (track_length < 0)
goto failed;
if (track_length < 300 && !burn_track_is_open_ended(tar[i])) { if (track_length < 300 && !burn_track_is_open_ended(tar[i])) {
track_length = 300; track_length = 300;
if (!tar[i]->pad) if (!tar[i]->pad)
tar[i]->pad = 1; tar[i]->pad = 1;
burn_track_set_sectors(tar[i], track_length); burn_track_set_sectors(tar[i], (off_t) track_length);
} }
type_to_form(tar[i]->mode, &ctladr, &form); type_to_form(tar[i]->mode, &ctladr, &form);
@ -723,7 +725,7 @@ struct cue_sheet *burn_create_toc_entries(struct burn_write_opts *o,
runtime += 150; runtime += 150;
} else if (pform != form) { } else if (pform != form) {
/* ts A70121 : This seems to be thw wrong test. Correct would /* ts A70121 : This seems to be the wrong test. Correct would
be to compare tar[]->mode or bit2 of ctladr. be to compare tar[]->mode or bit2 of ctladr.
*/ */
@ -1025,7 +1027,7 @@ static int burn_write_leadin_cdtext(struct burn_write_opts *o,
} }
#endif /* Libburn_debug_cd_texT */ #endif /* Libburn_debug_cd_texT */
err = d->write(d, write_lba, buf); err = d->write(d, (off_t) write_lba, buf);
if (err == BE_CANCELLED) if (err == BE_CANCELLED)
{ ret = 0; goto ex; } { ret = 0; goto ex; }
write_lba += sectors; write_lba += sectors;
@ -1072,10 +1074,10 @@ ex:;
} }
/* ts A61218 : outsourced from burn_write_track() */ /* ts A61218 / C40303 : outsourced from burn_write_track() */
int burn_disc_init_track_status(struct burn_write_opts *o, int burn_disc_init_track_status(struct burn_write_opts *o,
struct burn_session *s, struct burn_track *t, struct burn_session *s, struct burn_track *t,
int tnum, int sectors) int tnum, off_t sectors)
{ {
struct burn_drive *d = o->drive; struct burn_drive *d = o->drive;
@ -1177,8 +1179,8 @@ int burn_write_track(struct burn_write_opts *o, struct burn_session *s,
/* <<< */ /* <<< */
sprintf(msg, sprintf(msg,
"TAO pre-track %2.2d : get_nwa(%d)=%d, d=%d , demand=%.f , cap=%.f\n", "TAO pre-track %2.2d : get_nwa(%d)=%d, d=%.f , demand=%.f , cap=%.f\n",
tnum+1, nwa, ret, d->nwa, tnum+1, nwa, ret, (double) d->nwa,
(double) burn_track_get_sectors_2(t, 1) * 2048.0, (double) burn_track_get_sectors_2(t, 1) * 2048.0,
(double) d->media_capacity_remaining); (double) d->media_capacity_remaining);
libdax_msgs_submit(libdax_messenger, d->global_index, libdax_msgs_submit(libdax_messenger, d->global_index,
@ -1203,9 +1205,11 @@ int burn_write_track(struct burn_write_opts *o, struct burn_session *s,
/* user data */ /* user data */
sectors = burn_track_get_sectors_2(t, 1); sectors = burn_track_get_sectors_2(t, 1);
if (sectors < 0)
{ ret = 0; goto ex; }
open_ended = burn_track_is_open_ended(t); open_ended = burn_track_is_open_ended(t);
burn_disc_init_track_status(o, s, t, tnum, sectors); burn_disc_init_track_status(o, s, t, tnum, (off_t) sectors);
/* ts A61030 : this cannot happen. tnum is always < s->tracks */ /* ts A61030 : this cannot happen. tnum is always < s->tracks */
if (tnum == s->tracks) if (tnum == s->tracks)
@ -1354,7 +1358,7 @@ int burn_disc_init_write_status(struct burn_write_opts *o,
d->progress.buffer_capacity = 0; d->progress.buffer_capacity = 0;
d->progress.buffer_available = 0; d->progress.buffer_available = 0;
d->progress.buffered_bytes = 0; d->progress.buffered_bytes = 0;
d->progress.buffer_min_fill = 0xffffffff; d->progress.buffer_min_fill = 0x7fffffffffffffff;
/* ts A70711 */ /* ts A70711 */
d->pessimistic_buffer_free = 0; d->pessimistic_buffer_free = 0;
@ -1566,8 +1570,8 @@ int burn_disc_open_track_dvd_minus_r(struct burn_write_opts *o,
d->send_write_parameters(d, NULL, -1, o); d->send_write_parameters(d, NULL, -1, o);
ret = d->get_nwa(d, -1, &lba, &nwa); ret = d->get_nwa(d, -1, &lba, &nwa);
sprintf(msg, sprintf(msg,
"DVD pre-track %2.2d : get_nwa(%d), ret= %d , d->nwa= %d", "DVD pre-track %2.2d : get_nwa(%d), ret= %d , d->nwa= %.f",
tnum+1, nwa, ret, d->nwa); tnum+1, nwa, ret, (double) d->nwa);
libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002, libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, msg,0,0); LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, msg,0,0);
if (nwa > d->nwa) if (nwa > d->nwa)
@ -1591,6 +1595,8 @@ int burn_disc_open_track_dvd_minus_r(struct burn_write_opts *o,
if (o->write_type == BURN_WRITE_SAO) { /* DAO */ if (o->write_type == BURN_WRITE_SAO) { /* DAO */
size = ((off_t) burn_track_get_sectors_2(s->track[tnum], 1)) size = ((off_t) burn_track_get_sectors_2(s->track[tnum], 1))
* (off_t) 2048; * (off_t) 2048;
if (size < 0)
{ret = 0; goto ex;}
/* Eventually round track size up to write chunk */ /* Eventually round track size up to write chunk */
if (o->obs_pad && (size % o->obs)) if (o->obs_pad && (size % o->obs))
@ -1626,8 +1632,8 @@ int burn_disc_open_track_dvd_plus_r(struct burn_write_opts *o,
BURN_ALLOC_MEM(msg, char, 160); BURN_ALLOC_MEM(msg, char, 160);
ret = d->get_nwa(d, -1, &lba, &nwa); ret = d->get_nwa(d, -1, &lba, &nwa);
sprintf(msg, sprintf(msg,
"DVD+R pre-track %2.2d : get_nwa(%d), ret= %d , d->nwa= %d", "DVD+R pre-track %2.2d : get_nwa(%d), ret= %d , d->nwa= %.f",
tnum+1, nwa, ret, d->nwa); tnum+1, nwa, ret, (double) d->nwa);
libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002, libdax_msgs_submit(libdax_messenger, d->global_index, 0x00000002,
LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, msg,0,0); LIBDAX_MSGS_SEV_DEBUG, LIBDAX_MSGS_PRIO_ZERO, msg,0,0);
if (nwa > d->nwa) if (nwa > d->nwa)
@ -1640,6 +1646,8 @@ int burn_disc_open_track_dvd_plus_r(struct burn_write_opts *o,
/* Reserve track */ /* Reserve track */
size = ((off_t) burn_track_get_sectors_2(s->track[tnum], 1)) size = ((off_t) burn_track_get_sectors_2(s->track[tnum], 1))
* (off_t) 2048; * (off_t) 2048;
if (size < 0)
{ret = 0; goto ex;}
if (o->obs_pad) { if (o->obs_pad) {
/* Round track size up to write chunk size */ /* Round track size up to write chunk size */
/* o->obs should be 32k or 64k already. But 32k /* o->obs should be 32k or 64k already. But 32k
@ -1650,16 +1658,6 @@ int burn_disc_open_track_dvd_plus_r(struct burn_write_opts *o,
size += (off_t) (o->obs - (size % o->obs)); size += (off_t) (o->obs - (size % o->obs));
} }
/* <<< Only for now until the first DVD+R succeeded */
if (!o->obs_pad) {
sprintf(msg, "Program error: encountered DVD+R without chunk padding");
libdax_msgs_submit(libdax_messenger, d->global_index,
0x00000004,
LIBDAX_MSGS_SEV_FATAL, LIBDAX_MSGS_PRIO_HIGH,
msg, 0, 0);
{ret = 0; goto ex;}
}
ret = d->reserve_track(d, size); ret = d->reserve_track(d, size);
if (ret <= 0) { if (ret <= 0) {
sprintf(msg, "Cannot reserve track of %.f bytes", sprintf(msg, "Cannot reserve track of %.f bytes",
@ -1899,11 +1897,14 @@ int burn_dvd_write_track(struct burn_write_opts *o,
struct buffer *out = d->buffer; struct buffer *out = d->buffer;
int sectors; int sectors;
int i, open_ended = 0, ret= 0, is_flushed = 0, track_open = 0; int i, open_ended = 0, ret= 0, is_flushed = 0, track_open = 0;
int first_buf_cap = 0, further_cap = 0, buf_cap_step = 1024; off_t first_buf_cap = 0, further_cap = 0, buf_cap_step = 1024;
/* ts A70213 : eventually expand size of track to max */ /* ts A70213 : eventually expand size of track to max */
burn_track_apply_fillup(t, d->media_capacity_remaining, 0); burn_track_apply_fillup(t, d->media_capacity_remaining, 0);
/* ts C00806 : Consider the track state changed by try to open */
d->medium_state_changed = 1;
if (d->current_profile == 0x11 || d->current_profile == 0x14 || if (d->current_profile == 0x11 || d->current_profile == 0x14 ||
d->current_profile == 0x15) { d->current_profile == 0x15) {
/* DVD-R, DVD-RW Sequential, DVD-R/DL Sequential */ /* DVD-R, DVD-RW Sequential, DVD-R/DL Sequential */
@ -1929,11 +1930,13 @@ int burn_dvd_write_track(struct burn_write_opts *o,
track_open = 1; track_open = 1;
sectors = burn_track_get_sectors_2(t, 1); sectors = burn_track_get_sectors_2(t, 1);
if (sectors < 0)
{ret = 0; goto ex;}
open_ended = burn_track_is_open_ended(t); open_ended = burn_track_is_open_ended(t);
/* (offset padding is done within sector_data()) */ /* (offset padding is done within sector_data()) */
burn_disc_init_track_status(o, s, t, tnum, sectors); burn_disc_init_track_status(o, s, t, tnum, (off_t) sectors);
for (i = 0; open_ended || i < sectors; i++) { for (i = 0; open_ended || i < sectors; i++) {
/* From time to time inquire drive buffer */ /* From time to time inquire drive buffer */
@ -2097,7 +2100,7 @@ int burn_dvd_write_session(struct burn_write_opts *o,
is not readable. is not readable.
By default the open session gets closed here before the new By default the open session gets closed here before the new
session is written. E.g. after writing a small dummy seesion session is written. E.g. after writing a small dummy session
number 2 one can read session 1 and write session 3 which number 2 one can read session 1 and write session 3 which
points to data of session 1. points to data of session 1.
@ -2230,7 +2233,8 @@ int burn_disc_setup_dvd_minus_rw(struct burn_write_opts *o,
if (o->start_byte >= 0) { if (o->start_byte >= 0) {
d->nwa = o->start_byte / 32768; /* align to 32 kB */ d->nwa = o->start_byte / 32768; /* align to 32 kB */
sprintf(msg, "Write start address is %d * 32768", d->nwa); sprintf(msg, "Write start address is %.f * 32768",
(double) d->nwa);
libdax_msgs_submit(libdax_messenger, d->global_index, libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020127, 0x00020127,
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH, LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
@ -2332,8 +2336,8 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
d->nwa = 0; d->nwa = 0;
if (o->start_byte >= 0) { if (o->start_byte >= 0) {
d->nwa = o->start_byte / 2048; d->nwa = o->start_byte / 2048;
sprintf(msg, "Write start address is %d * 2048", sprintf(msg, "Write start address is %.f * 2048",
d->nwa); (double) d->nwa);
libdax_msgs_submit(libdax_messenger, d->global_index, libdax_msgs_submit(libdax_messenger, d->global_index,
0x00020127, 0x00020127,
LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH, LIBDAX_MSGS_SEV_NOTE, LIBDAX_MSGS_PRIO_HIGH,
@ -2423,9 +2427,17 @@ int burn_dvd_write_sync(struct burn_write_opts *o,
msg, 0, 0); msg, 0, 0);
goto early_failure; goto early_failure;
} }
/* ??? padding needed ??? cowardly doing it for now */ /* Unaligned BD-R track end works with various drives and
if (o->obs_pad < 2) produces exact READ CAPACITY results.
Nevertheless stream recording hates unaligned WRITE.
With DVD+R it seems that obs_pad is silently applied by the
drive if a non-aligned final WRITE is received.
*/
if (o->obs_pad < 2 &&
!(d->current_profile == 0x41 && !d->do_stream_recording &&
o->bdr_obs_exempt))
o->obs_pad = 1; /* fill-up track's last obs buffer */ o->obs_pad = 1; /* fill-up track's last obs buffer */
if (d->current_profile == 0x41) /* BD-R */ if (d->current_profile == 0x41) /* BD-R */
o->obs = Libburn_bd_r_obS; o->obs = Libburn_bd_r_obS;
if (d->do_stream_recording) { if (d->do_stream_recording) {
@ -2647,7 +2659,7 @@ ex:;
/* ts A70910 : to be used as burn_drive.write(), emulating mmc_write() */ /* ts A70910 : to be used as burn_drive.write(), emulating mmc_write() */
int burn_stdio_mmc_write(struct burn_drive *d, int start, struct buffer *buf) int burn_stdio_mmc_write(struct burn_drive *d, off_t start, struct buffer *buf)
{ {
int ret; int ret;
off_t start_byte; off_t start_byte;
@ -2690,7 +2702,7 @@ int burn_stdio_mmc_write(struct burn_drive *d, int start, struct buffer *buf)
/* ts A70910 : to be used as burn_drive.write(), /* ts A70910 : to be used as burn_drive.write(),
emulating mmc_write() with simulated writing. */ emulating mmc_write() with simulated writing. */
int burn_stdio_mmc_dummy_write(struct burn_drive *d, int start, int burn_stdio_mmc_dummy_write(struct burn_drive *d, off_t start,
struct buffer *buf) struct buffer *buf)
{ {
if (d->cancel) if (d->cancel)
@ -2762,30 +2774,57 @@ void burn_stdio_mmc_sync_cache(struct burn_drive *d)
} }
/* ts A70912 */ /* ts C00824 : API */
/* Enforces eventual nominal write speed. /* Enforces nominal write speed */
@param flag bit0= initialize *prev_time */ int burn_nominal_slowdown(int kb_per_second, int max_corr,
int burn_stdio_slowdown(struct burn_drive *d, struct timeval *prev_time, struct timeval *prev_time,
int amount, int flag) int *us_corr, off_t b_since_prev, int flag)
{ {
struct timeval tnow; struct timeval tnow;
double to_wait; double to_wait, goal, corr;
int abs_max_corr;
if (flag & 1) { if (flag & 1) {
gettimeofday(prev_time, NULL); gettimeofday(prev_time, NULL);
*us_corr = 0;
return 1; return 1;
} }
if(d->nominal_write_speed <= 0) if (kb_per_second <= 0)
return 2; return 2;
if (max_corr < -1.0e9 || max_corr > 1.0e9)
abs_max_corr = 1000000000;
else
abs_max_corr = abs(max_corr);
gettimeofday(&tnow, NULL); gettimeofday(&tnow, NULL);
to_wait = ( ((double) amount) / (double) d->nominal_write_speed ) - goal = ((double) b_since_prev) / 1000.0 / ((double) kb_per_second) +
(double) ( tnow.tv_sec - prev_time->tv_sec ) - ((double) prev_time->tv_sec) +
(double) ( tnow.tv_usec - prev_time->tv_usec ) / 1.0e6 ((double) prev_time->tv_usec) / 1.0e6 +
- 0.001; /* best would be 1 / kernel granularity HZ */ ((double) *us_corr) / 1.0e6 ;
if (to_wait >= 0.0001) { to_wait = goal - ((double) tnow.tv_sec) -
usleep((int) (to_wait * 1000000.0)); ((double) tnow.tv_usec) / 1.0e6;
/* usleep might be restricted to 999999 microseconds */
while (to_wait > 0.0) {
if (to_wait >= 0.5) {
usleep(500000);
to_wait -= 0.5;
} else if (to_wait >= 0.00001) {
usleep((int) (to_wait * 1000000.0));
to_wait = 0.0;
} else {
to_wait = 0.0;
}
} }
gettimeofday(prev_time, NULL); gettimeofday(prev_time, NULL);
corr = (goal - ((double) prev_time->tv_sec) -
((double) prev_time->tv_usec) / 1.0e6) * 1.0e6;
if (corr > abs_max_corr)
*us_corr = abs_max_corr;
else if (corr < -abs_max_corr)
*us_corr = -abs_max_corr;
else
*us_corr = corr;
return 1; return 1;
} }
@ -2794,17 +2833,20 @@ int burn_stdio_slowdown(struct burn_drive *d, struct timeval *prev_time,
int burn_stdio_write_track(struct burn_write_opts *o, struct burn_session *s, int burn_stdio_write_track(struct burn_write_opts *o, struct burn_session *s,
int tnum, int flag) int tnum, int flag)
{ {
int open_ended, bufsize = 16 * 2048, ret, sectors; int open_ended, bufsize = 16 * 2048, ret;
struct burn_track *t = s->track[tnum]; struct burn_track *t = s->track[tnum];
struct burn_drive *d = o->drive; struct burn_drive *d = o->drive;
char *buf = NULL; char *buf = NULL;
int i, prev_sync_sector = 0; int us_corr = 0, max_corr = 250000;
off_t prev_sync_sector = 0, sectors, i;
struct buffer *out = d->buffer; struct buffer *out = d->buffer;
struct timeval prev_time; struct timeval prev_time;
BURN_ALLOC_MEM(buf, char, bufsize); BURN_ALLOC_MEM(buf, char, bufsize);
sectors = burn_track_get_sectors_2(t, 1); sectors = burn_track_get_sectors_2_v2(t, 1);
if (sectors < 0)
{ret = 0; goto ex;}
burn_disc_init_track_status(o, s, t, tnum, sectors); burn_disc_init_track_status(o, s, t, tnum, sectors);
open_ended = burn_track_is_open_ended(t); open_ended = burn_track_is_open_ended(t);
@ -2818,7 +2860,10 @@ int burn_stdio_write_track(struct burn_write_opts *o, struct burn_session *s,
d->do_simulate = o->simulate; d->do_simulate = o->simulate;
d->sync_cache = burn_stdio_mmc_sync_cache; d->sync_cache = burn_stdio_mmc_sync_cache;
burn_stdio_slowdown(d, &prev_time, 0, 1); /* initialize */ /* initialize */
burn_nominal_slowdown(d->nominal_write_speed, max_corr,
&prev_time, &us_corr, (off_t) 0, 1);
for (i = 0; open_ended || i < sectors; i++) { for (i = 0; open_ended || i < sectors; i++) {
/* transact a (CD sized) sector */ /* transact a (CD sized) sector */
if (!sector_data(o, t, 0)) if (!sector_data(o, t, 0))
@ -2831,14 +2876,25 @@ int burn_stdio_write_track(struct burn_write_opts *o, struct burn_session *s,
} }
d->progress.sector++; d->progress.sector++;
/* Flush to disk from time to time */ /* Flush to disk from time to time */
if (d->progress.sector - prev_sync_sector >= if (o->stdio_fsync_size > 0) {
o->stdio_fsync_size && o->stdio_fsync_size > 0) { if (d->progress.sector - prev_sync_sector >=
prev_sync_sector = d->progress.sector; o->stdio_fsync_size) {
if (!o->simulate) if (!o->simulate)
burn_stdio_sync_cache(d->stdio_fd, d, 1); burn_stdio_sync_cache(d->stdio_fd, d,
1);
burn_nominal_slowdown(
d->nominal_write_speed, max_corr,
&prev_time, &us_corr,
(off_t) (d->progress.sector -
prev_sync_sector) *
(off_t) 2048,
0);
prev_sync_sector = d->progress.sector;
}
} else if ((d->progress.sector % 512) == 0) {
burn_nominal_slowdown(d->nominal_write_speed, max_corr,
&prev_time, &us_corr, (off_t) (512 * 2048), 0);
} }
if ((d->progress.sector % 512) == 0)
burn_stdio_slowdown(d, &prev_time, 512 * 2, 0);
} }
/* Pad up buffer to next full o->obs (usually 32 kB) */ /* Pad up buffer to next full o->obs (usually 32 kB) */
@ -3074,6 +3130,7 @@ return crap. so we send the command, then ignore the result.
/* goto fail_wo_sync; */ /* goto fail_wo_sync; */
#endif /* Libburn_write_with_function_print_cuE */ #endif /* Libburn_write_with_function_print_cuE */
d->medium_state_changed = 1;
ret = 1; ret = 1;
if (o->write_type == BURN_WRITE_SAO) if (o->write_type == BURN_WRITE_SAO)
ret = d->send_cue_sheet(d, sheet); ret = d->send_cue_sheet(d, sheet);