mirror of
https://code.videolan.org/videolan/vlc
synced 2024-09-04 09:11:33 +02:00
*Merged hh patch in libdvdcss from main tree.
*Updated local libdvdread, so that it does not depend on libdvdcss (ala dummy_dvdcss) and modified configure to reflect changes.
This commit is contained in:
parent
b7ee1eeafe
commit
b08376be72
111
configure
vendored
111
configure
vendored
@ -6286,6 +6286,7 @@ if test "${with_dvdcss+set}" = set; then
|
||||
CFLAGS_DVD="${CFLAGS_DVD} -I../../extras/libdvdcss"
|
||||
LIB_DVD="${LIB_DVD} lib/libdvdcss.a ${LIB_LIBDVDCSS}"
|
||||
LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}"
|
||||
LIB_DVDREAD="${LIB_DVDREAD} lib/libdvdread.a lib/libdvdcss.a ${LIB_LIBDVDCSS}"
|
||||
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}"
|
||||
fi
|
||||
;;
|
||||
@ -6298,6 +6299,7 @@ if test "${with_dvdcss+set}" = set; then
|
||||
CFLAGS_DVD="${CFLAGS_DVD} -I../../extras/libdvdcss"
|
||||
LIB_DVD="${LIB_DVD} -Llib -ldvdcss"
|
||||
LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} -L../../lib -ldvdcss"
|
||||
LIB_DVDREAD="${LIB_DVD} -Llib -ldvdread -ldvdcss"
|
||||
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -L../../lib -ldvdcss"
|
||||
fi
|
||||
;;
|
||||
@ -6310,6 +6312,7 @@ if test "${with_dvdcss+set}" = set; then
|
||||
CFLAGS_DVD="${CFLAGS_DVD} -DLIBDVDCSS_VERSION=\"${LIBDVDCSS_VERSION}\""
|
||||
LIB_DVD="${LIB_DVD} -ldl"
|
||||
LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} -ldl"
|
||||
LIB_DVDREAD="${LIB_DVDREAD} lib/libdvdread.a -ldl"
|
||||
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -ldl"
|
||||
;;
|
||||
*)
|
||||
@ -6323,7 +6326,8 @@ if test "${with_dvdcss+set}" = set; then
|
||||
fi
|
||||
LIB_DVD="${LIB_DVD} -ldvdcss"
|
||||
LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} -ldvdcss"
|
||||
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -ldvdcss"
|
||||
LIB_DVDREAD="${LIB_DVDREAD} -ldvdread -ldvdcss"
|
||||
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -ldvdread -ldvdcss"
|
||||
esac
|
||||
else
|
||||
# user didn't decide, we choose to use local libdvdcss and link statically
|
||||
@ -6336,7 +6340,8 @@ else
|
||||
CFLAGS_DVD="${CFLAGS_DVD} -I../../extras/libdvdcss"
|
||||
LIB_DVD="${LIB_DVD} lib/libdvdcss.a ${LIB_LIBDVDCSS}"
|
||||
LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}"
|
||||
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}"
|
||||
LIB_DVDREAD="${LIB_DVDREAD} lib/libdvdread.a lib/libdvdcss.a ${LIB_LIBDVDCSS}"
|
||||
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} ../../lib/libdvdread.a ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}"
|
||||
else
|
||||
# XXX: no check for libdl is done, don't try this at home !
|
||||
DUMMY_LIBDVDCSS=1
|
||||
@ -6345,6 +6350,7 @@ else
|
||||
CFLAGS_DVD="${CFLAGS_DVD} -DGOD_DAMN_DMCA"
|
||||
LIB_DVD="${LIB_DVD} -ldl"
|
||||
LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} -ldl"
|
||||
LIB_DVDREAD="${LIB_DVDREAD} lib/libdvdread.a -ldl"
|
||||
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -ldl"
|
||||
fi
|
||||
fi
|
||||
@ -6355,11 +6361,8 @@ if test "${enable_dvdread+set}" = set; then
|
||||
enableval="$enable_dvdread"
|
||||
if test x$enableval = xyes
|
||||
then
|
||||
NEED_LIBDVDCSS=1
|
||||
STATIC_LIBDVDCSS=1
|
||||
BUILTINS="${BUILTINS} dvdread"
|
||||
CFLAGS_DVDREAD="${CFLAGS_DVDREAD} -I../../extras/libdvdread"
|
||||
LIB_DVDREAD="${LIB_DVDREAD} lib/libdvdread.a lib/libdvdcss.a"
|
||||
CFLAGS_DVDREAD="${CFLAGS_DVD} ${CFLAGS_DVDREAD} -I../../extras/libdvdread"
|
||||
fi
|
||||
fi
|
||||
|
||||
@ -6374,7 +6377,7 @@ fi
|
||||
if test x$enable_vcd != xno
|
||||
then
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 6378 "configure"
|
||||
#line 6381 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <linux/cdrom.h>
|
||||
EOF
|
||||
@ -6448,17 +6451,17 @@ if test "${with_mad+set}" = set; then
|
||||
do
|
||||
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
|
||||
echo "configure:6452: checking for $ac_hdr" >&5
|
||||
echo "configure:6455: checking for $ac_hdr" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 6457 "configure"
|
||||
#line 6460 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <$ac_hdr>
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:6462: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:6465: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
|
||||
if test -z "$ac_err"; then
|
||||
rm -rf conftest*
|
||||
@ -6488,7 +6491,7 @@ fi
|
||||
done
|
||||
|
||||
echo $ac_n "checking for mad_bit_init in -lmad""... $ac_c" 1>&6
|
||||
echo "configure:6492: checking for mad_bit_init in -lmad" >&5
|
||||
echo "configure:6495: checking for mad_bit_init in -lmad" >&5
|
||||
ac_lib_var=`echo mad'_'mad_bit_init | sed 'y%./+-%__p_%'`
|
||||
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
@ -6496,7 +6499,7 @@ else
|
||||
ac_save_LIBS="$LIBS"
|
||||
LIBS="-lmad $LIBS"
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 6500 "configure"
|
||||
#line 6503 "configure"
|
||||
#include "confdefs.h"
|
||||
/* Override any gcc2 internal prototype to avoid an error. */
|
||||
/* We use char because int might match the return type of a gcc2
|
||||
@ -6507,7 +6510,7 @@ int main() {
|
||||
mad_bit_init()
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:6511: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
if { (eval echo configure:6514: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
rm -rf conftest*
|
||||
eval "ac_cv_lib_$ac_lib_var=yes"
|
||||
else
|
||||
@ -6574,7 +6577,7 @@ if test "${enable_esd+set}" = set; then
|
||||
# Extract the first word of "esd-config", so it can be a program name with args.
|
||||
set dummy esd-config; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:6578: checking for $ac_word" >&5
|
||||
echo "configure:6581: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_ESD_CONFIG'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@ -6625,7 +6628,7 @@ if test "${enable_arts+set}" = set; then
|
||||
# Extract the first word of "artsc-config", so it can be a program name with args.
|
||||
set dummy artsc-config; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:6629: checking for $ac_word" >&5
|
||||
echo "configure:6632: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_ARTS_CONFIG'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@ -6683,17 +6686,17 @@ else
|
||||
do
|
||||
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
|
||||
echo "configure:6687: checking for $ac_hdr" >&5
|
||||
echo "configure:6690: checking for $ac_hdr" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 6692 "configure"
|
||||
#line 6695 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <$ac_hdr>
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:6697: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:6700: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
|
||||
if test -z "$ac_err"; then
|
||||
rm -rf conftest*
|
||||
@ -6738,17 +6741,17 @@ fi
|
||||
do
|
||||
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
|
||||
echo "configure:6742: checking for $ac_hdr" >&5
|
||||
echo "configure:6745: checking for $ac_hdr" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 6747 "configure"
|
||||
#line 6750 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <$ac_hdr>
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:6752: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:6755: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
|
||||
if test -z "$ac_err"; then
|
||||
rm -rf conftest*
|
||||
@ -6836,7 +6839,7 @@ fi
|
||||
# Extract the first word of "sdl12-config", so it can be a program name with args.
|
||||
set dummy sdl12-config; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:6840: checking for $ac_word" >&5
|
||||
echo "configure:6843: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_SDL12_CONFIG'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@ -6876,7 +6879,7 @@ fi
|
||||
# Extract the first word of "sdl11-config", so it can be a program name with args.
|
||||
set dummy sdl11-config; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:6880: checking for $ac_word" >&5
|
||||
echo "configure:6883: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_SDL11_CONFIG'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@ -6917,7 +6920,7 @@ fi
|
||||
# Extract the first word of "sdl-config", so it can be a program name with args.
|
||||
set dummy sdl-config; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:6921: checking for $ac_word" >&5
|
||||
echo "configure:6924: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_SDL_CONFIG'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@ -6963,17 +6966,17 @@ fi
|
||||
do
|
||||
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
|
||||
echo "configure:6967: checking for $ac_hdr" >&5
|
||||
echo "configure:6970: checking for $ac_hdr" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 6972 "configure"
|
||||
#line 6975 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <$ac_hdr>
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:6977: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:6980: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
|
||||
if test -z "$ac_err"; then
|
||||
rm -rf conftest*
|
||||
@ -7043,17 +7046,17 @@ fi
|
||||
do
|
||||
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
|
||||
echo "configure:7047: checking for $ac_hdr" >&5
|
||||
echo "configure:7050: checking for $ac_hdr" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 7052 "configure"
|
||||
#line 7055 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <$ac_hdr>
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:7057: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:7060: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
|
||||
if test -z "$ac_err"; then
|
||||
rm -rf conftest*
|
||||
@ -7082,7 +7085,7 @@ done
|
||||
|
||||
else
|
||||
echo $ac_n "checking for directX headers in ${withval}""... $ac_c" 1>&6
|
||||
echo "configure:7086: checking for directX headers in ${withval}" >&5
|
||||
echo "configure:7089: checking for directX headers in ${withval}" >&5
|
||||
if test -f ${withval}/include/directx.h
|
||||
then
|
||||
PLUGINS="${PLUGINS} directx"
|
||||
@ -7179,7 +7182,7 @@ if test "${enable_gnome+set}" = set; then
|
||||
# Extract the first word of "gnome-config", so it can be a program name with args.
|
||||
set dummy gnome-config; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:7183: checking for $ac_word" >&5
|
||||
echo "configure:7186: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_GNOME_CONFIG'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@ -7224,17 +7227,17 @@ fi
|
||||
do
|
||||
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
|
||||
echo "configure:7228: checking for $ac_hdr" >&5
|
||||
echo "configure:7231: checking for $ac_hdr" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 7233 "configure"
|
||||
#line 7236 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <$ac_hdr>
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:7238: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:7241: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
|
||||
if test -z "$ac_err"; then
|
||||
rm -rf conftest*
|
||||
@ -7294,7 +7297,7 @@ fi
|
||||
# Extract the first word of "gtk-config", so it can be a program name with args.
|
||||
set dummy gtk-config; ac_word=$2
|
||||
echo $ac_n "checking for $ac_word""... $ac_c" 1>&6
|
||||
echo "configure:7298: checking for $ac_word" >&5
|
||||
echo "configure:7301: checking for $ac_word" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_path_GTK_CONFIG'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
@ -7344,17 +7347,17 @@ fi
|
||||
do
|
||||
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
|
||||
echo "configure:7348: checking for $ac_hdr" >&5
|
||||
echo "configure:7351: checking for $ac_hdr" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 7353 "configure"
|
||||
#line 7356 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <$ac_hdr>
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:7358: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:7361: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
|
||||
if test -z "$ac_err"; then
|
||||
rm -rf conftest*
|
||||
@ -7411,17 +7414,17 @@ if test x$enable_x11 != xno &&
|
||||
do
|
||||
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
|
||||
echo "configure:7415: checking for $ac_hdr" >&5
|
||||
echo "configure:7418: checking for $ac_hdr" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 7420 "configure"
|
||||
#line 7423 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <$ac_hdr>
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:7425: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:7428: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
|
||||
if test -z "$ac_err"; then
|
||||
rm -rf conftest*
|
||||
@ -7474,17 +7477,17 @@ if test x$enable_xvideo != xno &&
|
||||
do
|
||||
ac_safe=`echo "$ac_hdr" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for $ac_hdr""... $ac_c" 1>&6
|
||||
echo "configure:7478: checking for $ac_hdr" >&5
|
||||
echo "configure:7481: checking for $ac_hdr" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 7483 "configure"
|
||||
#line 7486 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <$ac_hdr>
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:7488: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:7491: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
|
||||
if test -z "$ac_err"; then
|
||||
rm -rf conftest*
|
||||
@ -7508,7 +7511,7 @@ EOF
|
||||
saved_CFLAGS=$CFLAGS
|
||||
CFLAGS="$CFLAGS -L$x_libraries -lX11 -lXext"
|
||||
echo $ac_n "checking for XvSetPortAttribute in -lXv_pic""... $ac_c" 1>&6
|
||||
echo "configure:7512: checking for XvSetPortAttribute in -lXv_pic" >&5
|
||||
echo "configure:7515: checking for XvSetPortAttribute in -lXv_pic" >&5
|
||||
ac_lib_var=`echo Xv_pic'_'XvSetPortAttribute | sed 'y%./+-%__p_%'`
|
||||
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
@ -7516,7 +7519,7 @@ else
|
||||
ac_save_LIBS="$LIBS"
|
||||
LIBS="-lXv_pic $LIBS"
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 7520 "configure"
|
||||
#line 7523 "configure"
|
||||
#include "confdefs.h"
|
||||
/* Override any gcc2 internal prototype to avoid an error. */
|
||||
/* We use char because int might match the return type of a gcc2
|
||||
@ -7527,7 +7530,7 @@ int main() {
|
||||
XvSetPortAttribute()
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:7531: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
if { (eval echo configure:7534: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
rm -rf conftest*
|
||||
eval "ac_cv_lib_$ac_lib_var=yes"
|
||||
else
|
||||
@ -7571,17 +7574,17 @@ if test "${enable_alsa+set}" = set; then
|
||||
then
|
||||
ac_safe=`echo "alsa/asoundlib.h" | sed 'y%./+-%__p_%'`
|
||||
echo $ac_n "checking for alsa/asoundlib.h""... $ac_c" 1>&6
|
||||
echo "configure:7575: checking for alsa/asoundlib.h" >&5
|
||||
echo "configure:7578: checking for alsa/asoundlib.h" >&5
|
||||
if eval "test \"`echo '$''{'ac_cv_header_$ac_safe'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
else
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 7580 "configure"
|
||||
#line 7583 "configure"
|
||||
#include "confdefs.h"
|
||||
#include <alsa/asoundlib.h>
|
||||
EOF
|
||||
ac_try="$ac_cpp conftest.$ac_ext >/dev/null 2>conftest.out"
|
||||
{ (eval echo configure:7585: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
{ (eval echo configure:7588: \"$ac_try\") 1>&5; (eval $ac_try) 2>&5; }
|
||||
ac_err=`grep -v '^ *+' conftest.out | grep -v "^conftest.${ac_ext}\$"`
|
||||
if test -z "$ac_err"; then
|
||||
rm -rf conftest*
|
||||
@ -7598,7 +7601,7 @@ fi
|
||||
if eval "test \"`echo '$ac_cv_header_'$ac_safe`\" = yes"; then
|
||||
echo "$ac_t""yes" 1>&6
|
||||
echo $ac_n "checking for main in -lasound""... $ac_c" 1>&6
|
||||
echo "configure:7602: checking for main in -lasound" >&5
|
||||
echo "configure:7605: checking for main in -lasound" >&5
|
||||
ac_lib_var=`echo asound'_'main | sed 'y%./+-%__p_%'`
|
||||
if eval "test \"`echo '$''{'ac_cv_lib_$ac_lib_var'+set}'`\" = set"; then
|
||||
echo $ac_n "(cached) $ac_c" 1>&6
|
||||
@ -7606,14 +7609,14 @@ else
|
||||
ac_save_LIBS="$LIBS"
|
||||
LIBS="-lasound $LIBS"
|
||||
cat > conftest.$ac_ext <<EOF
|
||||
#line 7610 "configure"
|
||||
#line 7613 "configure"
|
||||
#include "confdefs.h"
|
||||
|
||||
int main() {
|
||||
main()
|
||||
; return 0; }
|
||||
EOF
|
||||
if { (eval echo configure:7617: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
if { (eval echo configure:7620: \"$ac_link\") 1>&5; (eval $ac_link) 2>&5; } && test -s conftest${ac_exeext}; then
|
||||
rm -rf conftest*
|
||||
eval "ac_cv_lib_$ac_lib_var=yes"
|
||||
else
|
||||
|
15
configure.in
15
configure.in
@ -767,6 +767,7 @@ AC_ARG_WITH(dvdcss,
|
||||
CFLAGS_DVD="${CFLAGS_DVD} -I../../extras/libdvdcss"
|
||||
LIB_DVD="${LIB_DVD} lib/libdvdcss.a ${LIB_LIBDVDCSS}"
|
||||
LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}"
|
||||
LIB_DVDREAD="${LIB_DVDREAD} lib/libdvdread.a lib/libdvdcss.a ${LIB_LIBDVDCSS}"
|
||||
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}"
|
||||
fi
|
||||
;;
|
||||
@ -779,6 +780,7 @@ AC_ARG_WITH(dvdcss,
|
||||
CFLAGS_DVD="${CFLAGS_DVD} -I../../extras/libdvdcss"
|
||||
LIB_DVD="${LIB_DVD} -Llib -ldvdcss"
|
||||
LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} -L../../lib -ldvdcss"
|
||||
LIB_DVDREAD="${LIB_DVD} -Llib -ldvdread -ldvdcss"
|
||||
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -L../../lib -ldvdcss"
|
||||
fi
|
||||
;;
|
||||
@ -791,6 +793,7 @@ AC_ARG_WITH(dvdcss,
|
||||
CFLAGS_DVD="${CFLAGS_DVD} -DLIBDVDCSS_VERSION=\"${LIBDVDCSS_VERSION}\""
|
||||
LIB_DVD="${LIB_DVD} -ldl"
|
||||
LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} -ldl"
|
||||
LIB_DVDREAD="${LIB_DVDREAD} lib/libdvdread.a -ldl"
|
||||
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -ldl"
|
||||
;;
|
||||
*)
|
||||
@ -804,7 +807,8 @@ AC_ARG_WITH(dvdcss,
|
||||
fi
|
||||
LIB_DVD="${LIB_DVD} -ldvdcss"
|
||||
LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} -ldvdcss"
|
||||
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -ldvdcss"
|
||||
LIB_DVDREAD="${LIB_DVDREAD} -ldvdread -ldvdcss"
|
||||
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -ldvdread -ldvdcss"
|
||||
esac ],
|
||||
# user didn't decide, we choose to use local libdvdcss and link statically
|
||||
# if libdvdcss is in the archive, or to use the dummy replacement otherwise.
|
||||
@ -816,7 +820,8 @@ AC_ARG_WITH(dvdcss,
|
||||
CFLAGS_DVD="${CFLAGS_DVD} -I../../extras/libdvdcss"
|
||||
LIB_DVD="${LIB_DVD} lib/libdvdcss.a ${LIB_LIBDVDCSS}"
|
||||
LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}"
|
||||
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}"
|
||||
LIB_DVDREAD="${LIB_DVDREAD} lib/libdvdread.a lib/libdvdcss.a ${LIB_LIBDVDCSS}"
|
||||
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} ../../lib/libdvdread.a ../../lib/libdvdcss.a ${LIB_LIBDVDCSS}"
|
||||
else
|
||||
# XXX: no check for libdl is done, don't try this at home !
|
||||
DUMMY_LIBDVDCSS=1
|
||||
@ -825,6 +830,7 @@ AC_ARG_WITH(dvdcss,
|
||||
CFLAGS_DVD="${CFLAGS_DVD} -DGOD_DAMN_DMCA"
|
||||
LIB_DVD="${LIB_DVD} -ldl"
|
||||
LIB_DVD_PLUGIN="${LIB_DVD_PLUGIN} -ldl"
|
||||
LIB_DVDREAD="${LIB_DVDREAD} lib/libdvdread.a -ldl"
|
||||
LIB_DVDREAD_PLUGIN="${LIB_DVDREAD_PLUGIN} -ldl"
|
||||
fi ])
|
||||
|
||||
@ -835,11 +841,8 @@ AC_ARG_ENABLE(dvdread,
|
||||
[ --enable-dvdread Enable dvdread support (default disabled)],
|
||||
[ if test x$enableval = xyes
|
||||
then
|
||||
NEED_LIBDVDCSS=1
|
||||
STATIC_LIBDVDCSS=1
|
||||
BUILTINS="${BUILTINS} dvdread"
|
||||
CFLAGS_DVDREAD="${CFLAGS_DVDREAD} -I../../extras/libdvdread"
|
||||
LIB_DVDREAD="${LIB_DVDREAD} lib/libdvdread.a lib/libdvdcss.a"
|
||||
CFLAGS_DVDREAD="${CFLAGS_DVD} ${CFLAGS_DVDREAD} -I../../extras/libdvdread"
|
||||
fi ])
|
||||
|
||||
dnl
|
||||
|
@ -2,7 +2,7 @@
|
||||
* css.c: Functions for DVD authentification and unscrambling
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999-2001 VideoLAN
|
||||
* $Id: css.c,v 1.21 2002/01/21 07:00:21 gbazin Exp $
|
||||
* $Id: css.c,v 1.22 2002/01/23 03:15:31 stef Exp $
|
||||
*
|
||||
* Author: Stéphane Borel <stef@via.ecp.fr>
|
||||
* Håkan Hjort <d95hjort@dtek.chalmers.se>
|
||||
@ -54,6 +54,7 @@
|
||||
/*****************************************************************************
|
||||
* Local prototypes
|
||||
*****************************************************************************/
|
||||
static int CSSAuth ( dvdcss_handle dvdcss );
|
||||
static int CSSGetASF ( dvdcss_handle dvdcss );
|
||||
static void CSSCryptKey ( int i_key_type, int i_varient,
|
||||
u8 const * p_challenge, u8* p_key );
|
||||
@ -92,55 +93,56 @@ int CSSTest( dvdcss_handle dvdcss )
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* CSSAuth : CSS Structure initialisation and DVD authentication.
|
||||
* CSSAuth : DVD CSS authentication.
|
||||
*****************************************************************************
|
||||
* It simulates the mutual authentication between logical unit and host.
|
||||
* Since we don't need the disc key to find the title key, we just run the
|
||||
* basic unavoidable commands to authenticate device and disc.
|
||||
* It simulates the mutual authentication between logical unit and host,
|
||||
* and stops when a session key (called bus key) has been established.
|
||||
* Always do the full auth sequence. Some drives seem to lie and always
|
||||
* respond with ASF=1. For instance the old DVD roms on Compaq Armada says
|
||||
* that ASF=1 from the start and then later fail with a 'read of scrambled
|
||||
* block without authentication' error.
|
||||
*****************************************************************************/
|
||||
int CSSAuth( dvdcss_handle dvdcss )
|
||||
static int CSSAuth( dvdcss_handle dvdcss )
|
||||
{
|
||||
/* structures defined in cdrom.h or dvdio.h */
|
||||
unsigned char p_buffer[10];
|
||||
char psz_warning[48];
|
||||
int i_ret = -1;
|
||||
int i;
|
||||
u8 p_buffer[10];
|
||||
u8 p_challenge[2*KEY_SIZE];
|
||||
dvd_key_t p_key1;
|
||||
dvd_key_t p_key2;
|
||||
dvd_key_t p_key_check;
|
||||
u8 i_varient = 0;
|
||||
char psz_warning[48];
|
||||
int i_ret = -1;
|
||||
int i;
|
||||
|
||||
dvdcss->css.i_agid = 0;
|
||||
|
||||
/* Test authentication success */
|
||||
switch( CSSGetASF( dvdcss ) )
|
||||
/* So this isn't really necessary except for debuging. */
|
||||
if( CSSGetASF( dvdcss ) < 0 )
|
||||
{
|
||||
case -1:
|
||||
return -1;
|
||||
|
||||
case 1:
|
||||
_dvdcss_debug( dvdcss, "already authenticated" );
|
||||
break;
|
||||
|
||||
case 0:
|
||||
_dvdcss_debug( dvdcss, "need to authenticate" );
|
||||
break;
|
||||
_dvdcss_error( dvdcss, "fatal error in CSSAuth" );
|
||||
// ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); ??
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Init sequence, request AGID */
|
||||
for( i = 1; i < 4 ; ++i )
|
||||
{
|
||||
snprintf( psz_warning, sizeof(psz_warning), "requesting AGID %d", i );
|
||||
_dvdcss_debug( dvdcss, "requesting AGID" );
|
||||
i_ret = ioctl_ReportAgid( dvdcss->i_fd, &dvdcss->css.i_agid );
|
||||
|
||||
/* We might have to reset hung authentication processes in the drive
|
||||
by invalidating the corresponding AGID'. As long as we haven't got
|
||||
an AGID, invalidate one (in sequence) and try again. */
|
||||
for( i = 0; i_ret == -1 && i < 4 ; ++i )
|
||||
{
|
||||
_dvdcss_debug( dvdcss, "ioctl_ReportAgid failed" );
|
||||
|
||||
sprintf( psz_warning, "invalidating AGID %d", i );
|
||||
_dvdcss_debug( dvdcss, psz_warning );
|
||||
|
||||
i_ret = ioctl_ReportAgid( dvdcss->i_fd, &dvdcss->css.i_agid );
|
||||
|
||||
if( i_ret != -1 )
|
||||
{
|
||||
/* No error during ioctl: we know the device is authenticated */
|
||||
break;
|
||||
}
|
||||
|
||||
_dvdcss_error( dvdcss, "ioctl_ReportAgid failed, invalidating" );
|
||||
|
||||
dvdcss->css.i_agid = 0;
|
||||
/* This is really _not good_, should be handled by the OS.
|
||||
Invalidating an AGID could make another process fail some
|
||||
where in it's authentication process. */
|
||||
dvdcss->css.i_agid = i;
|
||||
ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid );
|
||||
|
||||
_dvdcss_debug( dvdcss, "requesting AGID" );
|
||||
i_ret = ioctl_ReportAgid( dvdcss->i_fd, &dvdcss->css.i_agid );
|
||||
}
|
||||
|
||||
/* Unable to authenticate without AGID */
|
||||
@ -150,21 +152,23 @@ int CSSAuth( dvdcss_handle dvdcss )
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Setup a challenge, any valuse should work */
|
||||
for( i = 0 ; i < 10; ++i )
|
||||
{
|
||||
dvdcss->css.disc.p_challenge[i] = i;
|
||||
p_challenge[i] = i;
|
||||
}
|
||||
|
||||
/* Get challenge from host */
|
||||
for( i = 0 ; i < 10 ; ++i )
|
||||
{
|
||||
p_buffer[9-i] = dvdcss->css.disc.p_challenge[i];
|
||||
p_buffer[9-i] = p_challenge[i];
|
||||
}
|
||||
|
||||
/* Send challenge to LU */
|
||||
if( ioctl_SendChallenge( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0 )
|
||||
{
|
||||
_dvdcss_error( dvdcss, "ioctl_SendChallenge failed" );
|
||||
// ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); ??
|
||||
return -1;
|
||||
}
|
||||
|
||||
@ -172,27 +176,26 @@ int CSSAuth( dvdcss_handle dvdcss )
|
||||
if( ioctl_ReportKey1( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0)
|
||||
{
|
||||
_dvdcss_error( dvdcss, "ioctl_ReportKey1 failed" );
|
||||
// ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); ??
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Send key1 to host */
|
||||
for( i = 0 ; i < KEY_SIZE ; i++ )
|
||||
{
|
||||
dvdcss->css.disc.p_key1[i] = p_buffer[4-i];
|
||||
p_key1[i] = p_buffer[4-i];
|
||||
}
|
||||
|
||||
for( i = 0 ; i < 32 ; ++i )
|
||||
{
|
||||
CSSCryptKey( 0, i, dvdcss->css.disc.p_challenge,
|
||||
dvdcss->css.disc.p_key_check );
|
||||
CSSCryptKey( 0, i, p_challenge, p_key_check );
|
||||
|
||||
if( memcmp( dvdcss->css.disc.p_key_check,
|
||||
dvdcss->css.disc.p_key1, KEY_SIZE ) == 0 )
|
||||
if( memcmp( p_key_check, p_key1, KEY_SIZE ) == 0 )
|
||||
{
|
||||
snprintf( psz_warning, sizeof(psz_warning),
|
||||
"drive authentic, using variant %d", i );
|
||||
"drive authentic, using varient %d", i );
|
||||
_dvdcss_debug( dvdcss, psz_warning );
|
||||
dvdcss->css.disc.i_varient = i;
|
||||
i_varient = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -200,73 +203,61 @@ int CSSAuth( dvdcss_handle dvdcss )
|
||||
if( i == 32 )
|
||||
{
|
||||
_dvdcss_error( dvdcss, "drive would not authenticate" );
|
||||
// ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); ??
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Get challenge from LU */
|
||||
if( ioctl_ReportChallenge( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0 )
|
||||
if( ioctl_ReportChallenge( dvdcss->i_fd,
|
||||
&dvdcss->css.i_agid, p_buffer ) < 0 )
|
||||
{
|
||||
_dvdcss_error( dvdcss, "ioctl_ReportKeyChallenge failed" );
|
||||
// ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); ??
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Send challenge to host */
|
||||
for( i = 0 ; i < 10 ; ++i )
|
||||
{
|
||||
dvdcss->css.disc.p_challenge[i] = p_buffer[9-i];
|
||||
p_challenge[i] = p_buffer[9-i];
|
||||
}
|
||||
|
||||
CSSCryptKey( 1, dvdcss->css.disc.i_varient,
|
||||
dvdcss->css.disc.p_challenge,
|
||||
dvdcss->css.disc.p_key2 );
|
||||
CSSCryptKey( 1, i_varient, p_challenge, p_key2 );
|
||||
|
||||
/* Get key2 from host */
|
||||
for( i = 0 ; i < KEY_SIZE ; ++i )
|
||||
{
|
||||
p_buffer[4-i] = dvdcss->css.disc.p_key2[i];
|
||||
p_buffer[4-i] = p_key2[i];
|
||||
}
|
||||
|
||||
/* Send key2 to LU */
|
||||
if( ioctl_SendKey2( dvdcss->i_fd, &dvdcss->css.i_agid, p_buffer ) < 0 )
|
||||
{
|
||||
_dvdcss_error( dvdcss, "ioctl_SendKey2 failed" );
|
||||
// ioctl_InvalidateAgid( dvdcss->i_fd, &dvdcss->css.i_agid ); ??
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The drive has accepted us as authentic. */
|
||||
_dvdcss_debug( dvdcss, "authentication established" );
|
||||
|
||||
memcpy( dvdcss->css.disc.p_challenge,
|
||||
dvdcss->css.disc.p_key1, KEY_SIZE );
|
||||
memcpy( dvdcss->css.disc.p_challenge+KEY_SIZE,
|
||||
dvdcss->css.disc.p_key2, KEY_SIZE );
|
||||
memcpy( p_challenge, p_key1, KEY_SIZE );
|
||||
memcpy( p_challenge + KEY_SIZE, p_key2, KEY_SIZE );
|
||||
|
||||
CSSCryptKey( 2, dvdcss->css.disc.i_varient,
|
||||
dvdcss->css.disc.p_challenge,
|
||||
dvdcss->css.disc.p_key_check );
|
||||
CSSCryptKey( 2, i_varient, p_challenge, dvdcss->css.p_bus_key );
|
||||
|
||||
_dvdcss_debug( dvdcss, "received session key" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( dvdcss->css.i_agid < 0 )
|
||||
{
|
||||
return -1;
|
||||
}
|
||||
/*****************************************************************************
|
||||
* CSSPrintKey : debug function that dumps a key value
|
||||
*****************************************************************************/static void CSSPrintKey( dvdcss_handle dvdcss, u8* data )
|
||||
{
|
||||
char psz_output[80];
|
||||
|
||||
/* Test authentication success */
|
||||
switch( CSSGetASF( dvdcss ) )
|
||||
{
|
||||
case -1:
|
||||
return -1;
|
||||
|
||||
case 1:
|
||||
_dvdcss_debug( dvdcss, "already authenticated" );
|
||||
return 0;
|
||||
|
||||
case 0:
|
||||
_dvdcss_debug( dvdcss, "need to get disc key" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return -1;
|
||||
sprintf( psz_output, "the key is %02x %02x %02x %02x %02x",
|
||||
data[0], data[1], data[2], data[3], data[4] );
|
||||
_dvdcss_debug( dvdcss, psz_output );
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
@ -279,7 +270,7 @@ int CSSAuth( dvdcss_handle dvdcss )
|
||||
*****************************************************************************/
|
||||
int CSSGetDiscKey( dvdcss_handle dvdcss )
|
||||
{
|
||||
unsigned char p_buffer[2048 + 4 + 1];
|
||||
unsigned char p_buffer[2048];
|
||||
#ifdef HAVE_CSSKEYS
|
||||
dvd_key_t disc_key;
|
||||
dvd_key_t test_key;
|
||||
@ -301,9 +292,8 @@ int CSSGetDiscKey( dvdcss_handle dvdcss )
|
||||
/* Unencrypt disc key using bus key */
|
||||
for( i = 0 ; i < 2048 ; i++ )
|
||||
{
|
||||
p_buffer[ i ] ^= dvdcss->css.disc.p_key_check[ 4 - (i % KEY_SIZE) ];
|
||||
p_buffer[ i ] ^= dvdcss->css.p_bus_key[ 4 - (i % KEY_SIZE) ];
|
||||
}
|
||||
memcpy( dvdcss->css.disc.p_disc_key, p_buffer, 2048 );
|
||||
|
||||
switch( dvdcss->i_method )
|
||||
{
|
||||
@ -316,14 +306,13 @@ int CSSGetDiscKey( dvdcss_handle dvdcss )
|
||||
{
|
||||
/* Take encrypted disc key and decrypt it */
|
||||
memcpy( disc_key,
|
||||
dvdcss->css.disc.p_disc_key
|
||||
+ playerkeys[i].i_offset,
|
||||
p_buffer + playerkeys[i].i_offset,
|
||||
KEY_SIZE );
|
||||
CSSDecryptKey( disc_key, playerkeys[i].p_key, 0 );
|
||||
|
||||
/* Encrypt disc key hash with disc key to
|
||||
* check we have disc key */
|
||||
memcpy( test_key, dvdcss->css.disc.p_disc_key, KEY_SIZE );
|
||||
memcpy( test_key, p_buffer, KEY_SIZE );
|
||||
CSSDecryptKey( test_key, disc_key, 0);
|
||||
|
||||
i++;
|
||||
@ -332,7 +321,7 @@ int CSSGetDiscKey( dvdcss_handle dvdcss )
|
||||
( memcmp( test_key, disc_key, KEY_SIZE ) ) );
|
||||
|
||||
/* The decrypted disk key will replace the disk key hash */
|
||||
memcpy( dvdcss->css.disc.p_disc_key, disc_key, KEY_SIZE );
|
||||
memcpy( dvdcss->css.p_disc_key, disc_key, KEY_SIZE );
|
||||
break;
|
||||
#else
|
||||
dvdcss->i_method = DVDCSS_METHOD_DISC;
|
||||
@ -341,13 +330,15 @@ int CSSGetDiscKey( dvdcss_handle dvdcss )
|
||||
/* Crack Disc key to be able to use it */
|
||||
_dvdcss_debug( dvdcss, "cracking disc key with key hash" );
|
||||
_dvdcss_debug( dvdcss, "building 64MB table ... this will take some time" );
|
||||
CSSDiscCrack( dvdcss, dvdcss->css.disc.p_disc_key );
|
||||
CSSDiscCrack( dvdcss, p_buffer );
|
||||
memcpy( dvdcss->css.p_disc_key, p_buffer, KEY_SIZE );
|
||||
break;
|
||||
|
||||
default:
|
||||
_dvdcss_debug( dvdcss, "disc key won't be decrypted" );
|
||||
}
|
||||
|
||||
CSSPrintKey( dvdcss, dvdcss->css.p_disc_key );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -449,6 +440,7 @@ int CSSGetTitleKey( dvdcss_handle dvdcss, int i_pos )
|
||||
if( b_stop_scanning )
|
||||
{
|
||||
memcpy( dvdcss->css.p_title_key, &p_key, sizeof(dvd_key_t) );
|
||||
CSSPrintKey( dvdcss, dvdcss->css.p_title_key );
|
||||
_dvdcss_debug( dvdcss, "vts key initialized" );
|
||||
return 0;
|
||||
}
|
||||
@ -456,6 +448,7 @@ int CSSGetTitleKey( dvdcss_handle dvdcss, int i_pos )
|
||||
if( !b_encrypted )
|
||||
{
|
||||
_dvdcss_debug( dvdcss, "file was unscrambled" );
|
||||
dvdcss->b_encrypted = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -489,13 +482,22 @@ int CSSGetTitleKey( dvdcss_handle dvdcss, int i_pos )
|
||||
/* Unencrypt title key using bus key */
|
||||
for( i = 0 ; i < KEY_SIZE ; i++ )
|
||||
{
|
||||
p_key[ i ] ^= dvdcss->css.disc.p_key_check[ 4 - (i % KEY_SIZE ) ];
|
||||
p_key[ i ] ^= dvdcss->css.p_bus_key[ 4 - (i % KEY_SIZE ) ];
|
||||
}
|
||||
|
||||
/* If p_key is all zero then there realy wasn't any key pressent. */
|
||||
if( !( p_key[0] | p_key[1] | p_key[2] | p_key[3] | p_key[4] ) )
|
||||
{
|
||||
memset( dvdcss->css.p_title_key, 0, sizeof(dvd_key_t) );
|
||||
CSSPrintKey( dvdcss, dvdcss->css.p_title_key );
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Title key decryption needs one inversion 0xff */
|
||||
CSSDecryptKey( p_key, dvdcss->css.disc.p_disc_key, 0xff );
|
||||
CSSDecryptKey( p_key, dvdcss->css.p_disc_key, 0xff );
|
||||
|
||||
memcpy( dvdcss->css.p_title_key, p_key, KEY_SIZE );
|
||||
CSSPrintKey( dvdcss, dvdcss->css.p_title_key );
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -558,29 +560,25 @@ int CSSDescrambleSector( dvd_key_t p_key, u8* p_sec )
|
||||
*****************************************************************************/
|
||||
static int CSSGetASF( dvdcss_handle dvdcss )
|
||||
{
|
||||
int i_agid;
|
||||
int i_asf = 0;
|
||||
|
||||
for( i_agid = 0 ; i_agid < 4 ; i_agid++ )
|
||||
if( ioctl_ReportASF( dvdcss->i_fd, NULL, &i_asf ) != 0 )
|
||||
{
|
||||
if( ioctl_ReportASF( dvdcss->i_fd, &i_agid, &i_asf ) == 0 )
|
||||
{
|
||||
if( i_asf )
|
||||
{
|
||||
_dvdcss_debug( dvdcss, "GetASF authenticated" );
|
||||
}
|
||||
else
|
||||
{
|
||||
_dvdcss_debug( dvdcss, "GetASF not authenticated" );
|
||||
}
|
||||
|
||||
return i_asf;
|
||||
}
|
||||
/* The ioctl process has failed */
|
||||
_dvdcss_error( dvdcss, "GetASF fatal error" );
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* The ioctl process has failed */
|
||||
_dvdcss_error( dvdcss, "GetASF fatal error" );
|
||||
return -1;
|
||||
if( i_asf )
|
||||
{
|
||||
_dvdcss_debug( dvdcss, "GetASF authenticated (ASF=1)" );
|
||||
}
|
||||
else
|
||||
{
|
||||
_dvdcss_debug( dvdcss, "GetASF not authenticated (ASF=0)" );
|
||||
}
|
||||
|
||||
return i_asf;
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
|
@ -2,7 +2,7 @@
|
||||
* css.h: Structures for DVD authentification and unscrambling
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999-2001 VideoLAN
|
||||
* $Id: css.h,v 1.7 2002/01/14 22:06:57 stef Exp $
|
||||
* $Id: css.h,v 1.8 2002/01/23 03:15:31 stef Exp $
|
||||
*
|
||||
* Author: Stéphane Borel <stef@via.ecp.fr>
|
||||
*
|
||||
@ -30,16 +30,6 @@
|
||||
|
||||
typedef u8 dvd_key_t[KEY_SIZE];
|
||||
|
||||
typedef struct disc_s
|
||||
{
|
||||
u8 p_challenge[2*KEY_SIZE];
|
||||
dvd_key_t p_key1;
|
||||
dvd_key_t p_key2;
|
||||
dvd_key_t p_key_check;
|
||||
u8 i_varient;
|
||||
u8 p_disc_key[2048];
|
||||
} disc_t;
|
||||
|
||||
typedef struct dvd_title_s
|
||||
{
|
||||
int i_startlb;
|
||||
@ -49,10 +39,11 @@ typedef struct dvd_title_s
|
||||
|
||||
typedef struct css_s
|
||||
{
|
||||
int i_agid;
|
||||
disc_t disc;
|
||||
dvd_key_t p_unenc_key; /* title key before decryption */
|
||||
dvd_key_t p_title_key; /* title key after decryption */
|
||||
int i_agid; /* Current Authenication Grant ID. */
|
||||
dvd_key_t p_bus_key; /* Current session key. */
|
||||
dvd_key_t p_disc_key; /* This DVD disc's key. */
|
||||
dvd_key_t p_unenc_key; /* Current title key before decryption. */
|
||||
dvd_key_t p_title_key; /* Current title key. */
|
||||
} css_t;
|
||||
|
||||
/*****************************************************************************
|
||||
@ -61,7 +52,6 @@ typedef struct css_s
|
||||
struct css_s;
|
||||
|
||||
int CSSTest ( dvdcss_handle );
|
||||
int CSSAuth ( dvdcss_handle );
|
||||
int CSSGetDiscKey ( dvdcss_handle );
|
||||
int CSSGetTitleKey ( dvdcss_handle, int );
|
||||
int CSSDescrambleSector ( u8 * , u8 * );
|
||||
|
@ -2,7 +2,7 @@
|
||||
* libdvdcss.c: DVD reading library.
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1998-2001 VideoLAN
|
||||
* $Id: libdvdcss.c,v 1.29 2002/01/21 07:00:21 gbazin Exp $
|
||||
* $Id: libdvdcss.c,v 1.30 2002/01/23 03:15:31 stef Exp $
|
||||
*
|
||||
* Authors: Stéphane Borel <stef@via.ecp.fr>
|
||||
* Samuel Hocevar <sam@zoy.org>
|
||||
@ -191,7 +191,6 @@ extern dvdcss_handle dvdcss_open ( char *psz_target )
|
||||
dvdcss->i_method = DVDCSS_METHOD_TITLE;
|
||||
dvdcss->b_ioctls = 0;
|
||||
dvdcss->b_encrypted = 1;
|
||||
memset( &dvdcss->css.disc, 0, sizeof(dvdcss->css.disc) );
|
||||
}
|
||||
|
||||
/* If disc is CSS protected and the ioctls work, authenticate the drive */
|
||||
@ -208,6 +207,7 @@ extern dvdcss_handle dvdcss_open ( char *psz_target )
|
||||
|
||||
memset( dvdcss->css.p_unenc_key, 0, KEY_SIZE );
|
||||
}
|
||||
memset( dvdcss->css.p_title_key, 0, KEY_SIZE );
|
||||
|
||||
#ifndef WIN32
|
||||
if( psz_raw_device != NULL )
|
||||
|
@ -25,7 +25,7 @@ CFLAGS := -I../../include -I../../extras $(CFLAGS)
|
||||
# Objects
|
||||
#
|
||||
|
||||
OBJ_C = dvdread.o dvd_udf.o nav_print.o nav_read.o ifo_print.o ifo_read.o
|
||||
OBJ_C = dvd_setup.o dvd_reader.o dvd_udf.o nav_print.o nav_read.o ifo_print.o ifo_read.o
|
||||
ALL_OBJ = $(OBJ_C) $(OBJ_LIBDVDREAD)
|
||||
|
||||
#
|
||||
@ -52,7 +52,7 @@ $(C_DEP): %.d: FORCE
|
||||
|
||||
$(OBJ_C): %.o: .dep/%.d
|
||||
$(OBJ_C): %.o: %.c
|
||||
$(CC) $(CFLAGS) $(CFLAGS_LIBDVDREAD) $(PCFLAGS) -c -o $@ $<
|
||||
$(CC) $(CFLAGS) $(CFLAGS_DVDREAD) $(CFLAGS_LIBDVDREAD) $(PCFLAGS) -c -o $@ $<
|
||||
|
||||
../../lib/$(FULL_SO): $(OBJ_C) $(OBJ_LIBDVDREAD)
|
||||
$(CC) $(PCFLAGS) $(ALL_SOFLAGS) -o $@ $^ $(PLCFLAGS) $(LIB_LIBDVDREAD)
|
||||
|
@ -20,7 +20,6 @@
|
||||
#ifndef BSWAP_H_INCLUDED
|
||||
#define BSWAP_H_INCLUDED
|
||||
|
||||
#include <defs.h>
|
||||
#include <config.h>
|
||||
|
||||
#if defined(WORDS_BIGENDIAN)
|
||||
|
@ -18,7 +18,7 @@
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/time.h> /* For the timing of dvdcss_title crack. */
|
||||
#include <sys/uio.h> /* readv() */
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
@ -26,7 +26,6 @@
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <dlfcn.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__)
|
||||
@ -47,45 +46,17 @@ typedef off_t off64_t;
|
||||
#define stat64 stat
|
||||
#endif
|
||||
|
||||
/* #include "dvdcss.h" */
|
||||
typedef struct dvdcss_s* dvdcss_handle;
|
||||
#define DVDCSS_NOFLAGS 0
|
||||
#define DVDCSS_INIT_QUIET (1 << 0)
|
||||
#define DVDCSS_INIT_DEBUG (1 << 1)
|
||||
#define DVDCSS_READ_DECRYPT (1 << 0)
|
||||
|
||||
#include "dvd_udf.h"
|
||||
#include "dvd_reader.h"
|
||||
|
||||
/**
|
||||
* Handle to the loaded dvdcss library.
|
||||
*/
|
||||
void *dvdcss_library = 0;
|
||||
|
||||
/**
|
||||
* libdvdcss functions.
|
||||
*/
|
||||
static dvdcss_handle (*dvdcss_open) ( char *psz_target,
|
||||
int i_flags );
|
||||
static int (*dvdcss_close) ( dvdcss_handle );
|
||||
static int (*dvdcss_title) ( dvdcss_handle,
|
||||
int i_block );
|
||||
static int (*dvdcss_seek) ( dvdcss_handle,
|
||||
int i_blocks );
|
||||
static int (*dvdcss_read) ( dvdcss_handle,
|
||||
void *p_buffer,
|
||||
int i_blocks,
|
||||
int i_title );
|
||||
static char * (*dvdcss_error) ( dvdcss_handle );
|
||||
#include "dvd_setup.h"
|
||||
|
||||
struct dvd_reader_s {
|
||||
/* Basic information. */
|
||||
int isImageFile;
|
||||
|
||||
/* Information required for an image file. */
|
||||
dvdcss_handle dev;
|
||||
int init_keys;
|
||||
int fd;
|
||||
dvd_handle dev;
|
||||
|
||||
/* Information required for a directory path drive. */
|
||||
char *path_root;
|
||||
@ -100,168 +71,32 @@ struct dvd_file_s {
|
||||
uint32_t seek_pos;
|
||||
|
||||
/* Information required for a directory path drive. */
|
||||
dvd_handle title_devs[9];
|
||||
size_t title_sizes[ 9 ];
|
||||
int title_fds[ 9 ];
|
||||
|
||||
/* Calculated at open-time, size in blocks. */
|
||||
ssize_t filesize;
|
||||
};
|
||||
|
||||
static void setupCSS( void )
|
||||
{
|
||||
if( !dvdcss_library ) {
|
||||
dvdcss_library = dlopen( "libdvdcss.so.0", RTLD_LAZY );
|
||||
|
||||
if( !dvdcss_library ) {
|
||||
fprintf( stderr, "libdvdread: Can't open libdvdcss: %s.\n",
|
||||
dlerror() );
|
||||
} else {
|
||||
#if defined(__OpenBSD__)
|
||||
#define U_S "_"
|
||||
#else
|
||||
#define U_S
|
||||
#endif
|
||||
dvdcss_open = (dvdcss_handle (*)(char*, int))
|
||||
dlsym( dvdcss_library, U_S "dvdcss_open" );
|
||||
dvdcss_close = (int (*)(dvdcss_handle))
|
||||
dlsym( dvdcss_library, U_S "dvdcss_close" );
|
||||
dvdcss_title = (int (*)(dvdcss_handle, int))
|
||||
dlsym( dvdcss_library, U_S "dvdcss_title" );
|
||||
dvdcss_seek = (int (*)(dvdcss_handle, int))
|
||||
dlsym( dvdcss_library, U_S "dvdcss_seek" );
|
||||
dvdcss_read = (int (*)(dvdcss_handle, void*, int, int))
|
||||
dlsym( dvdcss_library, U_S "dvdcss_read" );
|
||||
dvdcss_error = (char* (*)(dvdcss_handle))
|
||||
dlsym( dvdcss_library, U_S "dvdcss_error" );
|
||||
|
||||
if( dlsym( dvdcss_library, U_S "dvdcss_crack" ) ) {
|
||||
fprintf( stderr, "libdvdread: Old (pre-0.0.2) version of "
|
||||
"libdvdcss found.\n"
|
||||
"libdvdread: You should get the "
|
||||
"latest version from "
|
||||
"http://www.videolan.org/\n" );
|
||||
dlclose( dvdcss_library );
|
||||
dvdcss_library = 0;
|
||||
} else if( !dvdcss_open || !dvdcss_close || !dvdcss_seek ||
|
||||
!dvdcss_title || !dvdcss_read || !dvdcss_error ) {
|
||||
|
||||
fprintf( stderr, "libdvdread: Unknown incompatible version "
|
||||
"of libdvdcss found.\n"
|
||||
"libdvdread: Try to find a "
|
||||
"newer version of libdvdread?\n" );
|
||||
dlclose( dvdcss_library );
|
||||
dvdcss_library = 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if( !dvdcss_library ) {
|
||||
fprintf( stderr, "libdvdread: Encrypted DVD support unavailable.\n" );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/* Loop over all titles and call dvdcss_title to crack the keys. */
|
||||
static int initAllCSSKeys( dvd_reader_t *dvd )
|
||||
{
|
||||
|
||||
if( dvdcss_library ) {
|
||||
struct timeval all_s, all_e;
|
||||
struct timeval t_s, t_e;
|
||||
char filename[ MAX_UDF_FILE_NAME_LEN ];
|
||||
uint32_t start, len;
|
||||
int title;
|
||||
|
||||
fprintf( stderr, "\n" );
|
||||
fprintf( stderr, "libdvdread: Attempting to retrieve all CSS keys\n" );
|
||||
fprintf( stderr, "libdvdread: This can take a _long_ time, "
|
||||
"please be patient\n\n" );
|
||||
|
||||
gettimeofday(&all_s, NULL);
|
||||
|
||||
for( title = 0; title < 100; title++ ) {
|
||||
gettimeofday( &t_s, NULL );
|
||||
if( title == 0 ) {
|
||||
sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" );
|
||||
} else {
|
||||
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 0 );
|
||||
}
|
||||
start = UDFFindFile( dvd, filename, &len );
|
||||
if( start != 0 && len != 0 ) {
|
||||
/* Perform CSS key cracking for this title. */
|
||||
fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n",
|
||||
filename, start );
|
||||
if( dvdcss_title( dvd->dev, (int)start ) < 0 ) {
|
||||
fprintf( stderr, "libdvdread: Error cracking CSS key!!\n");
|
||||
}
|
||||
gettimeofday( &t_e, NULL );
|
||||
fprintf( stderr, "libdvdread: Elapsed time %ld\n",
|
||||
(long int) t_e.tv_sec - t_s.tv_sec );
|
||||
}
|
||||
|
||||
if( title == 0 ) continue;
|
||||
|
||||
gettimeofday( &t_s, NULL );
|
||||
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, 1 );
|
||||
start = UDFFindFile( dvd, filename, &len );
|
||||
if( start == 0 || len == 0 ) break;
|
||||
|
||||
/* Perform CSS key cracking for this title. */
|
||||
fprintf( stderr, "libdvdread: Get key for %s at 0x%08x\n",
|
||||
filename, start );
|
||||
if( dvdcss_title( dvd->dev, (int)start ) < 0 ) {
|
||||
fprintf( stderr, "libdvdread: Error cracking CSS key!!\n");
|
||||
}
|
||||
gettimeofday( &t_e, NULL );
|
||||
fprintf( stderr, "libdvdread: Elapsed time %ld\n",
|
||||
(long int) t_e.tv_sec - t_s.tv_sec );
|
||||
}
|
||||
title--;
|
||||
|
||||
fprintf( stderr, "libdvdread: Found %d VTS's\n", title );
|
||||
gettimeofday(&all_e, NULL);
|
||||
fprintf( stderr, "libdvdread: Elapsed time %ld\n",
|
||||
(long int) all_e.tv_sec - all_s.tv_sec );
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Open a DVD image or block device file.
|
||||
*/
|
||||
static dvd_reader_t *DVDOpenImageFile( const char *location )
|
||||
{
|
||||
dvd_reader_t *dvd;
|
||||
dvdcss_handle dev = 0;
|
||||
int fd = -1;
|
||||
dvd_handle dev = 0;
|
||||
|
||||
setupCSS();
|
||||
|
||||
if( dvdcss_library ) {
|
||||
dev = dvdcss_open( (char *) location, DVDCSS_INIT_DEBUG );
|
||||
if( !dev ) {
|
||||
fprintf( stderr, "libdvdread: Can't open %s for reading.\n",
|
||||
location );
|
||||
return 0;
|
||||
}
|
||||
} else {
|
||||
fd = open( location, O_RDONLY );
|
||||
if( fd < 0 ) {
|
||||
fprintf( stderr, "libdvdread: Can't open %s for reading.\n",
|
||||
location );
|
||||
return 0;
|
||||
}
|
||||
dev = pf_dvd_open( (char *) location );
|
||||
if( !dev ) {
|
||||
fprintf( stderr, "libdvdread: Can't open %s for reading.\n",
|
||||
location );
|
||||
return 0;
|
||||
}
|
||||
|
||||
dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) );
|
||||
if( !dvd ) return 0;
|
||||
dvd->isImageFile = 1;
|
||||
dvd->dev = dev;
|
||||
dvd->init_keys = 0;
|
||||
dvd->fd = fd;
|
||||
dvd->path_root = 0;
|
||||
|
||||
return dvd;
|
||||
@ -271,12 +106,11 @@ static dvd_reader_t *DVDOpenPath( const char *path_root )
|
||||
{
|
||||
dvd_reader_t *dvd;
|
||||
|
||||
fprintf(stderr, "libdvdread: opening %s as folder\n", path_root );
|
||||
dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) );
|
||||
if( !dvd ) return 0;
|
||||
dvd->isImageFile = 0;
|
||||
dvd->dev = 0;
|
||||
dvd->init_keys = 0;
|
||||
dvd->fd = -1;
|
||||
dvd->path_root = strdup( path_root );
|
||||
|
||||
return dvd;
|
||||
@ -335,106 +169,110 @@ dvd_reader_t *DVDOpen( const char *path )
|
||||
|
||||
ret = stat64( path, &fileinfo );
|
||||
if( ret < 0 ) {
|
||||
/* If we can't stat the file, give up */
|
||||
fprintf( stderr, "libdvdread: Can't stat %s\n", path );
|
||||
perror("");
|
||||
return 0;
|
||||
/* If we can't stat the file, give up */
|
||||
fprintf( stderr, "libdvdread: Can't stat %s\n", path );
|
||||
perror("");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* First check if this is a block/char device or a file*/
|
||||
if( S_ISBLK( fileinfo.st_mode ) ||
|
||||
S_ISCHR( fileinfo.st_mode ) ||
|
||||
S_ISREG( fileinfo.st_mode ) ) {
|
||||
/* Try to open libdvdcss or fall back to standard functions */
|
||||
DVDSetupRead();
|
||||
|
||||
/**
|
||||
* Block devices and regular files are assumed to be DVD-Video images.
|
||||
*/
|
||||
/* First check if this is a block/char device or a file */
|
||||
if( S_ISBLK( fileinfo.st_mode ) ||
|
||||
S_ISCHR( fileinfo.st_mode ) ||
|
||||
S_ISREG( fileinfo.st_mode ) ) {
|
||||
|
||||
/**
|
||||
* Block devices and regular files are assumed to be DVD-Video images.
|
||||
*/
|
||||
#if defined(__sun)
|
||||
return DVDOpenImageFile( sun_block2char( path ) );
|
||||
return DVDOpenImageFile( sun_block2char( path ) );
|
||||
#elif defined(SYS_BSD)
|
||||
return DVDOpenImageFile( bsd_block2char( path ) );
|
||||
return DVDOpenImageFile( bsd_block2char( path ) );
|
||||
#else
|
||||
return DVDOpenImageFile( path );
|
||||
return DVDOpenImageFile( path );
|
||||
#endif
|
||||
|
||||
} else if( S_ISDIR( fileinfo.st_mode ) ) {
|
||||
dvd_reader_t *auth_drive = 0;
|
||||
char *path_copy;
|
||||
dvd_reader_t *auth_drive = 0;
|
||||
char *path_copy;
|
||||
#if defined(SYS_BSD)
|
||||
struct fstab* fe;
|
||||
struct fstab* fe;
|
||||
#elif defined(__sun) || defined(__linux__)
|
||||
FILE *mntfile;
|
||||
FILE *mntfile;
|
||||
#endif
|
||||
|
||||
/* XXX: We should scream real loud here. */
|
||||
if( !(path_copy = strdup( path ) ) ) return 0;
|
||||
fprintf(stderr, "libdvdread: file is directory\n" );
|
||||
/* XXX: We should scream real loud here. */
|
||||
if( !(path_copy = strdup( path ) ) ) return 0;
|
||||
|
||||
/* Resolve any symlinks and get the absolut dir name. */
|
||||
{
|
||||
char *new_path;
|
||||
int cdir = open( ".", O_RDONLY );
|
||||
/* Resolve any symlinks and get the absolut dir name. */
|
||||
{
|
||||
char *new_path;
|
||||
int cdir = open( ".", O_RDONLY );
|
||||
|
||||
if( cdir >= 0 ) {
|
||||
chdir( path_copy );
|
||||
new_path = getcwd( NULL, PATH_MAX );
|
||||
fchdir( cdir );
|
||||
close( cdir );
|
||||
if( new_path ) {
|
||||
free( path_copy );
|
||||
path_copy = new_path;
|
||||
}
|
||||
}
|
||||
}
|
||||
if( cdir >= 0 ) {
|
||||
chdir( path_copy );
|
||||
new_path = getcwd( NULL, PATH_MAX );
|
||||
fchdir( cdir );
|
||||
close( cdir );
|
||||
if( new_path ) {
|
||||
free( path_copy );
|
||||
path_copy = new_path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If we're being asked to open a directory, check if that directory
|
||||
* is the mountpoint for a DVD-ROM which we can use instead.
|
||||
*/
|
||||
/**
|
||||
* If we're being asked to open a directory, check if that directory
|
||||
* is the mountpoint for a DVD-ROM which we can use instead.
|
||||
*/
|
||||
|
||||
if( strlen( path_copy ) > 1 ) {
|
||||
if( path[ strlen( path_copy ) - 1 ] == '/' )
|
||||
path_copy[ strlen( path_copy ) - 1 ] = '\0';
|
||||
}
|
||||
if( strlen( path_copy ) > 1 ) {
|
||||
if( path[ strlen( path_copy ) - 1 ] == '/' )
|
||||
path_copy[ strlen( path_copy ) - 1 ] = '\0';
|
||||
}
|
||||
|
||||
if( strlen( path_copy ) > 9 ) {
|
||||
if( !strcasecmp( &(path_copy[ strlen( path_copy ) - 9 ]),
|
||||
"/video_ts" ) ) {
|
||||
path_copy[ strlen( path_copy ) - 9 ] = '\0';
|
||||
}
|
||||
}
|
||||
if( strlen( path_copy ) > 9 ) {
|
||||
if( !strcasecmp( &(path_copy[ strlen( path_copy ) - 9 ]),
|
||||
"/video_ts" ) ) {
|
||||
path_copy[ strlen( path_copy ) - 9 ] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(SYS_BSD)
|
||||
if( ( fe = getfsfile( path_copy ) ) ) {
|
||||
char *dev_name = bsd_block2char( fe->fs_spec );
|
||||
fprintf( stderr,
|
||||
"libdvdread: Attempting to use device %s"
|
||||
" mounted on %s for CSS authentication\n",
|
||||
dev_name,
|
||||
fe->fs_file );
|
||||
auth_drive = DVDOpenImageFile( dev_name );
|
||||
free( dev_name );
|
||||
}
|
||||
if( ( fe = getfsfile( path_copy ) ) ) {
|
||||
char *dev_name = bsd_block2char( fe->fs_spec );
|
||||
fprintf( stderr,
|
||||
"libdvdread: Attempting to use device %s"
|
||||
" mounted on %s for CSS authentication\n",
|
||||
dev_name,
|
||||
fe->fs_file );
|
||||
auth_drive = DVDOpenImageFile( dev_name );
|
||||
free( dev_name );
|
||||
}
|
||||
#elif defined(__sun)
|
||||
mntfile = fopen( MNTTAB, "r" );
|
||||
if( mntfile ) {
|
||||
struct mnttab mp;
|
||||
int res;
|
||||
mntfile = fopen( MNTTAB, "r" );
|
||||
if( mntfile ) {
|
||||
struct mnttab mp;
|
||||
int res;
|
||||
|
||||
while( ( res = getmntent( mntfile, &mp ) ) != -1 ) {
|
||||
if( res == 0 && !strcmp( mp.mnt_mountp, path_copy ) ) {
|
||||
char *dev_name = sun_block2char( mp.mnt_special );
|
||||
fprintf( stderr,
|
||||
"libdvdread: Attempting to use device %s"
|
||||
" mounted on %s for CSS authentication\n",
|
||||
dev_name,
|
||||
mp.mnt_mountp );
|
||||
auth_drive = DVDOpenImageFile( dev_name );
|
||||
free( dev_name );
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose( mntfile );
|
||||
}
|
||||
while( ( res = getmntent( mntfile, &mp ) ) != -1 ) {
|
||||
if( res == 0 && !strcmp( mp.mnt_mountp, path_copy ) ) {
|
||||
char *dev_name = sun_block2char( mp.mnt_special );
|
||||
fprintf( stderr,
|
||||
"libdvdread: Attempting to use device %s"
|
||||
" mounted on %s for CSS authentication\n",
|
||||
dev_name,
|
||||
mp.mnt_mountp );
|
||||
auth_drive = DVDOpenImageFile( dev_name );
|
||||
free( dev_name );
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose( mntfile );
|
||||
}
|
||||
#elif defined(__linux__)
|
||||
mntfile = fopen( MOUNTED, "r" );
|
||||
if( mntfile ) {
|
||||
@ -442,24 +280,25 @@ dvd_reader_t *DVDOpen( const char *path )
|
||||
|
||||
while( ( me = getmntent( mntfile ) ) ) {
|
||||
if( !strcmp( me->mnt_dir, path_copy ) ) {
|
||||
fprintf( stderr,
|
||||
"libdvdread: Attempting to use device %s"
|
||||
fprintf( stderr,
|
||||
"libdvdread: Attempting to use device %s"
|
||||
" mounted on %s for CSS authentication\n",
|
||||
me->mnt_fsname,
|
||||
me->mnt_dir );
|
||||
me->mnt_dir );
|
||||
auth_drive = DVDOpenImageFile( me->mnt_fsname );
|
||||
break;
|
||||
}
|
||||
}
|
||||
fprintf(stderr, "libdvdread: mounted device %p\n", me );
|
||||
fclose( mntfile );
|
||||
}
|
||||
}
|
||||
#endif
|
||||
if( !auth_drive ) {
|
||||
fprintf( stderr, "libdvdread: Device inaccessible, "
|
||||
"CSS authentication not available.\n" );
|
||||
}
|
||||
if( !auth_drive ) {
|
||||
fprintf( stderr, "libdvdread: Device inaccessible, "
|
||||
"CSS authentication not available.\n" );
|
||||
}
|
||||
|
||||
free( path_copy );
|
||||
free( path_copy );
|
||||
|
||||
/**
|
||||
* If we've opened a drive, just use that.
|
||||
@ -469,7 +308,7 @@ dvd_reader_t *DVDOpen( const char *path )
|
||||
/**
|
||||
* Otherwise, we now try to open the directory tree instead.
|
||||
*/
|
||||
fprintf( stderr, "libdvdread: Using normal filesystem access.\n" );
|
||||
fprintf( stderr, "libdvdread: Using normal filesystem access.\n" );
|
||||
return DVDOpenPath( path );
|
||||
}
|
||||
|
||||
@ -481,8 +320,7 @@ dvd_reader_t *DVDOpen( const char *path )
|
||||
void DVDClose( dvd_reader_t *dvd )
|
||||
{
|
||||
if( dvd ) {
|
||||
if( dvd->dev ) dvdcss_close( dvd->dev );
|
||||
if( dvd->fd >= 0 ) close( dvd->fd );
|
||||
if( dvd->dev ) pf_dvd_close( dvd->dev );
|
||||
if( dvd->path_root ) free( dvd->path_root );
|
||||
free( dvd );
|
||||
dvd = 0;
|
||||
@ -500,12 +338,13 @@ static dvd_file_t *DVDOpenFileUDF( dvd_reader_t *dvd, char *filename )
|
||||
start = UDFFindFile( dvd, filename, &len );
|
||||
if( !start ) return 0;
|
||||
|
||||
fprintf( stderr, "libdvdread: opening %s as image\n", filename );
|
||||
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
|
||||
if( !dvd_file ) return 0;
|
||||
dvd_file->dvd = dvd;
|
||||
dvd_file->lb_start = start;
|
||||
dvd_file->seek_pos = 0;
|
||||
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) );
|
||||
//memset( dvd_file->title_devs, -1, sizeof( dvd_file->title_devs ) );
|
||||
dvd_file->filesize = len / DVD_VIDEO_LB_LEN;
|
||||
|
||||
return dvd_file;
|
||||
@ -576,13 +415,14 @@ static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename )
|
||||
char full_path[ PATH_MAX + 1 ];
|
||||
dvd_file_t *dvd_file;
|
||||
struct stat fileinfo;
|
||||
int fd;
|
||||
dvd_handle dev;
|
||||
|
||||
/* Get the full path of the file. */
|
||||
if( !findDVDFile( dvd, filename, full_path ) ) return 0;
|
||||
|
||||
fd = open( full_path, O_RDONLY );
|
||||
if( fd < 0 ) return 0;
|
||||
fprintf( stderr, "libdvdread: opening %s as file\n", full_path );
|
||||
dev = pf_dvd_open( full_path );
|
||||
if( dev == NULL ) return 0;
|
||||
|
||||
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
|
||||
if( !dvd_file ) return 0;
|
||||
@ -590,7 +430,7 @@ static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename )
|
||||
dvd_file->lb_start = 0;
|
||||
dvd_file->seek_pos = 0;
|
||||
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
|
||||
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) );
|
||||
memset( dvd_file->title_devs, -1, sizeof( dvd_file->title_devs ) );
|
||||
dvd_file->filesize = 0;
|
||||
|
||||
if( stat( full_path, &fileinfo ) < 0 ) {
|
||||
@ -599,19 +439,19 @@ static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename )
|
||||
return 0;
|
||||
}
|
||||
dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
|
||||
dvd_file->title_fds[ 0 ] = fd;
|
||||
dvd_file->title_devs[ 0 ] = dev;
|
||||
dvd_file->filesize = dvd_file->title_sizes[ 0 ];
|
||||
|
||||
return dvd_file;
|
||||
}
|
||||
|
||||
static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd,
|
||||
int title, int menu )
|
||||
static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd, int title, int menu )
|
||||
{
|
||||
char filename[ MAX_UDF_FILE_NAME_LEN ];
|
||||
uint32_t start, len;
|
||||
dvd_file_t *dvd_file;
|
||||
|
||||
fprintf( stderr, "libdvdread: opening VOB as image\n" );
|
||||
if( title == 0 ) {
|
||||
sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" );
|
||||
} else {
|
||||
@ -626,7 +466,7 @@ static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd,
|
||||
dvd_file->lb_start = start;
|
||||
dvd_file->seek_pos = 0;
|
||||
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
|
||||
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) );
|
||||
memset( dvd_file->title_devs, -1, sizeof( dvd_file->title_devs ) );
|
||||
dvd_file->filesize = len / DVD_VIDEO_LB_LEN;
|
||||
|
||||
/* Calculate the complete file size for every file in the VOBS */
|
||||
@ -640,27 +480,15 @@ static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd,
|
||||
}
|
||||
}
|
||||
|
||||
/* Hack to crack all the keys on the first open. */
|
||||
if( dvdcss_library ) {
|
||||
if( !dvd_file->dvd->init_keys ) {
|
||||
initAllCSSKeys( dvd_file->dvd );
|
||||
dvd_file->dvd->init_keys = 1;
|
||||
}
|
||||
}
|
||||
|
||||
/* Perform CSS key cracking for this title. */
|
||||
if( dvdcss_library ) {
|
||||
if( dvdcss_title( dvd_file->dvd->dev, (int)start ) < 0 ) {
|
||||
if( pf_dvd_seek( dvd_file->dvd->dev, (int)start, DVDCSS_SEEK_KEY ) < 0 ) {
|
||||
fprintf( stderr, "libdvdread: Error cracking CSS key for %s\n",
|
||||
filename );
|
||||
}
|
||||
}
|
||||
|
||||
return dvd_file;
|
||||
}
|
||||
|
||||
static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd,
|
||||
int title, int menu )
|
||||
static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd, int title, int menu )
|
||||
{
|
||||
char filename[ MAX_UDF_FILE_NAME_LEN ];
|
||||
char full_path[ PATH_MAX + 1 ];
|
||||
@ -668,17 +496,18 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd,
|
||||
dvd_file_t *dvd_file;
|
||||
int i;
|
||||
|
||||
fprintf( stderr, "libdvdread: opening VOB as file\n" );
|
||||
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
|
||||
if( !dvd_file ) return 0;
|
||||
dvd_file->dvd = dvd;
|
||||
dvd_file->lb_start = 0;
|
||||
dvd_file->seek_pos = 0;
|
||||
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
|
||||
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) );
|
||||
memset( dvd_file->title_devs, -1, sizeof( dvd_file->title_devs ) );
|
||||
dvd_file->filesize = 0;
|
||||
|
||||
if( menu ) {
|
||||
int fd;
|
||||
dvd_handle dev;
|
||||
|
||||
if( title == 0 ) {
|
||||
sprintf( filename, "VIDEO_TS.VOB" );
|
||||
@ -690,8 +519,8 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd,
|
||||
return 0;
|
||||
}
|
||||
|
||||
fd = open( full_path, O_RDONLY );
|
||||
if( fd < 0 ) {
|
||||
dev = pf_dvd_open( full_path );
|
||||
if( dev == NULL ) {
|
||||
free( dvd_file );
|
||||
return 0;
|
||||
}
|
||||
@ -702,7 +531,8 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd,
|
||||
return 0;
|
||||
}
|
||||
dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
|
||||
dvd_file->title_fds[ 0 ] = fd;
|
||||
dvd_file->title_devs[ 0 ] = dev;
|
||||
pf_dvd_title( dvd_file->title_devs[0], 0 );
|
||||
dvd_file->filesize = dvd_file->title_sizes[ 0 ];
|
||||
|
||||
} else {
|
||||
@ -719,7 +549,8 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd,
|
||||
}
|
||||
|
||||
dvd_file->title_sizes[ i ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
|
||||
dvd_file->title_fds[ i ] = open( full_path, O_RDONLY );
|
||||
dvd_file->title_devs[ i ] = pf_dvd_open( full_path );
|
||||
pf_dvd_title( dvd_file->title_devs[i], 0 );
|
||||
dvd_file->filesize += dvd_file->title_sizes[ i ];
|
||||
}
|
||||
if( !(dvd_file->title_sizes[ 0 ]) ) {
|
||||
@ -732,7 +563,7 @@ static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd,
|
||||
}
|
||||
|
||||
dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum,
|
||||
dvd_read_domain_t domain )
|
||||
dvd_read_domain_t domain )
|
||||
{
|
||||
char filename[ MAX_UDF_FILE_NAME_LEN ];
|
||||
|
||||
@ -785,8 +616,9 @@ void DVDCloseFile( dvd_file_t *dvd_file )
|
||||
if( dvd_file ) {
|
||||
if( !dvd_file->dvd->isImageFile ) {
|
||||
for( i = 0; i < 9; ++i ) {
|
||||
if( dvd_file->title_fds[ i ] >= 0 )
|
||||
close( dvd_file->title_fds[ i ] );
|
||||
if( dvd_file->title_devs[ i ] ) {
|
||||
pf_dvd_close( dvd_file->title_devs[i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -796,56 +628,37 @@ void DVDCloseFile( dvd_file_t *dvd_file )
|
||||
}
|
||||
|
||||
int64_t DVDReadLBUDF( dvd_reader_t *device, uint32_t lb_number,
|
||||
size_t block_count, unsigned char *data,
|
||||
int encrypted )
|
||||
size_t block_count, unsigned char *data,
|
||||
int encrypted )
|
||||
{
|
||||
if( dvdcss_library ) {
|
||||
int ret;
|
||||
int ret;
|
||||
|
||||
if( !device->dev ) {
|
||||
fprintf( stderr, "libdvdread: Fatal error in block read.\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = dvdcss_seek( device->dev, (int) lb_number );
|
||||
if( ret != (int) lb_number ) {
|
||||
fprintf( stderr, "libdvdread: Can't seek to block %u\n",
|
||||
lb_number );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int64_t) ( dvdcss_read( device->dev, (char *) data,
|
||||
(int) block_count, encrypted )
|
||||
* (uint64_t) DVD_VIDEO_LB_LEN );
|
||||
} else {
|
||||
off64_t off;
|
||||
|
||||
if( device->fd < 0) {
|
||||
fprintf( stderr, "libdvdread: Fatal error in block read.\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
off = lseek64( device->fd, lb_number * (int64_t) DVD_VIDEO_LB_LEN,
|
||||
SEEK_SET );
|
||||
if( off != ( lb_number * (int64_t) DVD_VIDEO_LB_LEN ) ) {
|
||||
fprintf( stderr, "libdvdread: Can't seek to block %u\n",
|
||||
lb_number );
|
||||
return 0;
|
||||
}
|
||||
return (int64_t) ( read( device->fd, data,
|
||||
block_count * DVD_VIDEO_LB_LEN ) );
|
||||
if( !device->dev ) {
|
||||
fprintf( stderr, "libdvdread: Fatal error in block read.\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = pf_dvd_seek( device->dev, (int) lb_number, DVDCSS_NOFLAGS );
|
||||
if( ret != (int) lb_number ) {
|
||||
fprintf( stderr, "libdvdread: Can't seek to block %u\n",
|
||||
lb_number );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int64_t) ( pf_dvd_read( device->dev, (char *) data,
|
||||
(int) block_count, encrypted )
|
||||
* (uint64_t) DVD_VIDEO_LB_LEN );
|
||||
}
|
||||
|
||||
static int64_t DVDReadBlocksUDF( dvd_file_t *dvd_file, uint32_t offset,
|
||||
size_t block_count, unsigned char *data )
|
||||
size_t block_count, unsigned char *data )
|
||||
{
|
||||
return DVDReadLBUDF( dvd_file->dvd, dvd_file->lb_start + offset,
|
||||
block_count, data, DVDCSS_READ_DECRYPT );
|
||||
}
|
||||
|
||||
static int64_t DVDReadBlocksPath( dvd_file_t *dvd_file, size_t offset,
|
||||
size_t block_count, unsigned char *data )
|
||||
size_t block_count, unsigned char *data )
|
||||
{
|
||||
int i;
|
||||
ssize_t ret, ret2;
|
||||
@ -858,70 +671,71 @@ static int64_t DVDReadBlocksPath( dvd_file_t *dvd_file, size_t offset,
|
||||
|
||||
if( offset < dvd_file->title_sizes[ i ] ) {
|
||||
if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] ) {
|
||||
off = lseek64( dvd_file->title_fds[ i ],
|
||||
offset * (int64_t) DVD_VIDEO_LB_LEN, SEEK_SET );
|
||||
if( off != ( offset * (int64_t) DVD_VIDEO_LB_LEN ) ) {
|
||||
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
|
||||
offset );
|
||||
return 0;
|
||||
}
|
||||
ret = read( dvd_file->title_fds[ i ], data,
|
||||
block_count * DVD_VIDEO_LB_LEN );
|
||||
off = pf_dvd_seek( dvd_file->title_devs[ i ], (int)offset, 0 );
|
||||
if( off != (int)offset ) {
|
||||
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
|
||||
offset );
|
||||
return 0;
|
||||
}
|
||||
ret = pf_dvd_read( dvd_file->title_devs[ i ], data,
|
||||
(int)block_count, DVDCSS_READ_DECRYPT );
|
||||
break;
|
||||
} else {
|
||||
size_t part1_size
|
||||
= ( dvd_file->title_sizes[ i ] - offset ) * DVD_VIDEO_LB_LEN;
|
||||
/* FIXME: Really needs to be a while loop.
|
||||
(This is only true if you try and read >1GB at a time) */
|
||||
size_t part1_size = dvd_file->title_sizes[ i ] - offset;
|
||||
/* FIXME: Really needs to be a while loop.
|
||||
* (This is only true if you try and read >1GB at a time) */
|
||||
|
||||
/* Read part 1 */
|
||||
off = lseek64( dvd_file->title_fds[ i ],
|
||||
offset * (int64_t) DVD_VIDEO_LB_LEN, SEEK_SET );
|
||||
if( off != ( offset * (int64_t) DVD_VIDEO_LB_LEN ) ) {
|
||||
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
|
||||
offset );
|
||||
return 0;
|
||||
}
|
||||
ret = read( dvd_file->title_fds[ i ], data, part1_size );
|
||||
if( ret < 0 ) return ret;
|
||||
/* FIXME: This is wrong if i is the last file in the set.
|
||||
also error from this read will not show in ret. */
|
||||
off = pf_dvd_seek( dvd_file->title_devs[ i ], offset, 0 );
|
||||
if( off != offset ) {
|
||||
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
|
||||
offset );
|
||||
return 0;
|
||||
}
|
||||
ret = pf_dvd_read( dvd_file->title_devs[ i ], data,
|
||||
part1_size, DVDCSS_READ_DECRYPT );
|
||||
if( ret < 0 ) return ret;
|
||||
/* FIXME: This is wrong if i is the last file in the set.
|
||||
* also error from this read will not show in ret. */
|
||||
|
||||
/* Read part 2 */
|
||||
lseek64( dvd_file->title_fds[ i + 1 ], (off64_t)0, SEEK_SET );
|
||||
ret2 = read( dvd_file->title_fds[ i + 1 ], data + part1_size,
|
||||
block_count * DVD_VIDEO_LB_LEN - part1_size );
|
||||
pf_dvd_seek( dvd_file->title_devs[ i + 1 ], 0, 0 );
|
||||
ret2 = pf_dvd_read( dvd_file->title_devs[ i + 1 ], data +
|
||||
( part1_size * (int64_t)DVD_VIDEO_LB_LEN ),
|
||||
block_count - part1_size,
|
||||
DVDCSS_READ_DECRYPT );
|
||||
if( ret2 < 0 ) return ret2;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
offset -= dvd_file->title_sizes[ i ];
|
||||
}
|
||||
}
|
||||
|
||||
return ( (int64_t) ret + (int64_t) ret2 );
|
||||
return ( (int64_t) ret + (int64_t) ret2 ) * DVD_VIDEO_LB_LEN;
|
||||
}
|
||||
|
||||
/* These are broken for some cases reading more than 2Gb at a time. */
|
||||
ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset,
|
||||
size_t block_count, unsigned char *data )
|
||||
size_t block_count, unsigned char *data )
|
||||
{
|
||||
int64_t ret;
|
||||
|
||||
if( dvd_file->dvd->isImageFile ) {
|
||||
ret = DVDReadBlocksUDF( dvd_file, (uint32_t)offset,
|
||||
block_count, data );
|
||||
ret = DVDReadBlocksUDF( dvd_file, (uint32_t)offset,
|
||||
block_count, data );
|
||||
} else {
|
||||
ret = DVDReadBlocksPath( dvd_file, (size_t) offset,
|
||||
block_count, data );
|
||||
ret = DVDReadBlocksPath( dvd_file, (size_t) offset,
|
||||
block_count, data );
|
||||
}
|
||||
if( ret <= 0 ) {
|
||||
return (ssize_t) ret;
|
||||
}
|
||||
|
||||
{
|
||||
ssize_t sret = (ssize_t) (ret / (int64_t)DVD_VIDEO_LB_LEN );
|
||||
if( sret == 0 ) {
|
||||
fprintf(stderr, "libdvdread: DVDReadBlocks got %d bytes\n", (int)ret );
|
||||
fprintf(stderr, "libdvdread: DVDReadBlocks got %d bytes\n", (int)ret );
|
||||
}
|
||||
return sret;
|
||||
}
|
||||
@ -933,13 +747,13 @@ int32_t DVDFileSeek( dvd_file_t *dvd_file, int32_t offset )
|
||||
dvd_file->seek_pos = (uint32_t) offset;
|
||||
return offset;
|
||||
} else {
|
||||
return (int32_t) ( lseek( dvd_file->title_fds[ 0 ],
|
||||
(off_t) offset, SEEK_SET ) );
|
||||
return (int32_t) ( lseek( dvd_file->title_devs[0]->i_fd,
|
||||
(off_t)offset, SEEK_SET ) );
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t DVDReadBytesUDF( dvd_file_t *dvd_file, void *data,
|
||||
size_t byte_size )
|
||||
size_t byte_size )
|
||||
{
|
||||
unsigned char *secbuf;
|
||||
unsigned int numsec, seek_sector, seek_byte;
|
||||
@ -951,8 +765,8 @@ static ssize_t DVDReadBytesUDF( dvd_file_t *dvd_file, void *data,
|
||||
numsec = ( ( seek_byte + byte_size ) / DVD_VIDEO_LB_LEN ) + 1;
|
||||
secbuf = (unsigned char *) malloc( numsec * DVD_VIDEO_LB_LEN );
|
||||
if( !secbuf ) {
|
||||
fprintf( stderr, "libdvdread: Can't allocate memory "
|
||||
"for file read!\n" );
|
||||
fprintf( stderr, "libdvdread: Can't allocate memory "
|
||||
"for file read!\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -972,9 +786,9 @@ static ssize_t DVDReadBytesUDF( dvd_file_t *dvd_file, void *data,
|
||||
}
|
||||
|
||||
static ssize_t DVDReadBytesPath( dvd_file_t *dvd_file, void *data,
|
||||
size_t byte_size )
|
||||
size_t byte_size )
|
||||
{
|
||||
return read( dvd_file->title_fds[ 0 ], data, byte_size );
|
||||
return read( dvd_file->title_devs[0]->i_fd, data, byte_size );
|
||||
}
|
||||
|
||||
ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size )
|
||||
@ -991,3 +805,121 @@ ssize_t DVDFileSize( dvd_file_t *dvd_file )
|
||||
return dvd_file->filesize;
|
||||
}
|
||||
|
||||
int64_t DVDReadVLBUDF( dvd_reader_t *device, uint32_t lb_number,
|
||||
size_t block_count, struct iovec * vector, int encrypted )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if( !device->dev ) {
|
||||
fprintf( stderr, "libdvdread: Fatal error in block read.\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = pf_dvd_seek( device->dev, (int) lb_number, 0 );
|
||||
if( ret != (int) lb_number ) {
|
||||
fprintf( stderr, "libdvdread: Can't seek to block %u\n",
|
||||
lb_number );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int64_t) ( pf_dvd_readv( device->dev, vector,
|
||||
(int)block_count, encrypted )
|
||||
* (uint64_t) DVD_VIDEO_LB_LEN );
|
||||
}
|
||||
|
||||
static int64_t DVDReadVBlocksUDF( dvd_file_t *dvd_file, uint32_t offset,
|
||||
size_t block_count, struct iovec *vector )
|
||||
{
|
||||
return DVDReadVLBUDF( dvd_file->dvd, dvd_file->lb_start + offset,
|
||||
block_count, vector, DVDCSS_READ_DECRYPT );
|
||||
}
|
||||
|
||||
static int64_t DVDReadVBlocksPath( dvd_file_t *dvd_file, size_t offset,
|
||||
size_t block_count, struct iovec *vector )
|
||||
{
|
||||
int i;
|
||||
int ret, ret2;
|
||||
int off;
|
||||
|
||||
ret = 0;
|
||||
ret2 = 0;
|
||||
for( i = 0 ; i < 9 ; ++i ) {
|
||||
if( !dvd_file->title_sizes[ i ] ) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( offset < dvd_file->title_sizes[ i ] ) {
|
||||
if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] ) {
|
||||
off = pf_dvd_seek( dvd_file->title_devs[ i ],
|
||||
(int)offset, 0 );
|
||||
if( off != (int)offset ) {
|
||||
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
|
||||
offset );
|
||||
return 0;
|
||||
}
|
||||
ret = pf_dvd_readv( dvd_file->title_devs[ i ], vector,
|
||||
(int)block_count, DVDCSS_READ_DECRYPT );
|
||||
break;
|
||||
} else {
|
||||
int part1_size = dvd_file->title_sizes[ i ] - offset;
|
||||
/* FIXME: Really needs to be a while loop.
|
||||
* (This is only true if you try and read >1GB at a time) */
|
||||
|
||||
/* Read part 1 */
|
||||
off = pf_dvd_seek( dvd_file->title_devs[ i ], offset, 0 );
|
||||
if( off != offset ) {
|
||||
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
|
||||
offset );
|
||||
return 0;
|
||||
}
|
||||
ret = pf_dvd_readv( dvd_file->title_devs[ i ], vector,
|
||||
part1_size, DVDCSS_READ_DECRYPT );
|
||||
|
||||
if( ret < 0 ) return ret;
|
||||
/* FIXME: This is wrong if i is the last file in the set.
|
||||
* also error from this read will not show in ret. */
|
||||
|
||||
/* Read part 2 */
|
||||
pf_dvd_seek( dvd_file->title_devs[ i + 1 ], 0, 0 );
|
||||
ret2 = pf_dvd_readv( dvd_file->title_devs[ i + 1 ],
|
||||
vector + part1_size,
|
||||
(int)(block_count - part1_size),
|
||||
DVDCSS_READ_DECRYPT );
|
||||
if( ret2 < 0 ) return ret2;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
offset -= dvd_file->title_sizes[ i ];
|
||||
}
|
||||
}
|
||||
|
||||
return ( ret + ret2 ) * (int64_t) DVD_VIDEO_LB_LEN;
|
||||
}
|
||||
|
||||
|
||||
ssize_t DVDReadVBlocks( dvd_file_t *dvd_file, int offset,
|
||||
size_t block_count, struct iovec * vector )
|
||||
{
|
||||
int64_t ret;
|
||||
|
||||
if( dvd_file->dvd->isImageFile ) {
|
||||
ret = DVDReadVBlocksUDF( dvd_file, (uint32_t)offset,
|
||||
block_count, vector );
|
||||
} else {
|
||||
ret = DVDReadVBlocksPath( dvd_file, (size_t) offset,
|
||||
block_count, vector );
|
||||
}
|
||||
if( ret <= 0 ) {
|
||||
return (ssize_t) ret;
|
||||
}
|
||||
|
||||
{
|
||||
ssize_t sret = (ssize_t) (ret / (int64_t)DVD_VIDEO_LB_LEN );
|
||||
if( sret == 0 )
|
||||
{
|
||||
fprintf(stderr, "libdvdread: DVDReadVBlocks got %d bytes\n", (int)ret );
|
||||
}
|
||||
return sret;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -111,6 +111,12 @@ void DVDCloseFile( dvd_file_t *dvd_file );
|
||||
ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset,
|
||||
size_t block_count, unsigned char *data );
|
||||
|
||||
/**
|
||||
* The same calling a readv-like function to fill a struct iovec.
|
||||
*/
|
||||
struct iovec;
|
||||
ssize_t DVDReadVBlocks( dvd_file_t *dvd_file, int offset,
|
||||
size_t block_count, struct iovec * vector );
|
||||
/**
|
||||
* Seek to the given position in the file. Returns the resulting position in
|
||||
* bytes from the beginning of the file. The seek position is only used for
|
||||
|
203
extras/libdvdread/dvd_setup.c
Normal file
203
extras/libdvdread/dvd_setup.c
Normal file
@ -0,0 +1,203 @@
|
||||
/**
|
||||
* dvd_setup.c: setup read functions with either libdvdcss
|
||||
* or minimal DVD access.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
* $Id: dvd_setup.c,v 1.1 2002/01/23 03:15:31 stef Exp $
|
||||
*
|
||||
* Authors: Samuel Hocevar <sam@zoy.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* Preamble
|
||||
*/
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#include <dlfcn.h>
|
||||
#include <sys/uio.h> /* struct iovec */
|
||||
|
||||
#include "dvd_reader.h"
|
||||
#include "dvd_setup.h"
|
||||
|
||||
#ifdef GOD_DAMN_DMCA
|
||||
/**
|
||||
* dvd_open: initialize library, open a DVD device.
|
||||
*/
|
||||
static dvd_handle dvd_open ( char *psz_target )
|
||||
{
|
||||
dvd_handle dev;
|
||||
|
||||
/* Allocate the library structure */
|
||||
dev = malloc( sizeof( dvd_handle ) );
|
||||
if( dev == NULL )
|
||||
{
|
||||
fprintf( stderr, "libdvdread: Could not allocate memory.\n" );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/* Open the device */
|
||||
dev->i_fd = open( psz_target, 0 );
|
||||
if( dev->i_fd < 0 )
|
||||
{
|
||||
fprintf( stderr, "libdvdread: Could not open device.\n" );
|
||||
free( dev );
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return dev;
|
||||
}
|
||||
|
||||
/**
|
||||
* dvd_error: return the last error message
|
||||
*/
|
||||
static char * dvd_error ( dvd_handle dev )
|
||||
{
|
||||
return "unknown error";
|
||||
}
|
||||
|
||||
/**
|
||||
* dvd_seek: seek into the device.
|
||||
*/
|
||||
static int dvd_seek ( dvd_handle dev, int i_blocks, int i_flags )
|
||||
{
|
||||
off_t i_read;
|
||||
|
||||
i_read = lseek( dev->i_fd,
|
||||
(off_t)i_blocks * (off_t)DVD_VIDEO_LB_LEN, SEEK_SET );
|
||||
|
||||
return i_read / DVD_VIDEO_LB_LEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* dvd_title: crack the current title key if needed.
|
||||
*/
|
||||
static int dvd_title ( dvd_handle dev, int i_block )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* dvd_read: read data from the device.
|
||||
*/
|
||||
static int dvd_read ( dvd_handle dev, void *p_buffer,
|
||||
int i_blocks,
|
||||
int i_flags )
|
||||
{
|
||||
int i_bytes;
|
||||
|
||||
i_bytes = read( dev->i_fd, p_buffer,
|
||||
(size_t)i_blocks * DVD_VIDEO_LB_LEN );
|
||||
|
||||
return i_bytes / DVD_VIDEO_LB_LEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* dvd_readv: read data to an iovec structure.
|
||||
*/
|
||||
static int dvd_readv ( dvd_handle dev, void *p_iovec,
|
||||
int i_blocks,
|
||||
int i_flags )
|
||||
{
|
||||
int i_read;
|
||||
|
||||
i_read = readv( dev->i_fd, (struct iovec*)p_iovec, i_blocks );
|
||||
|
||||
return i_read / DVD_VIDEO_LB_LEN;
|
||||
}
|
||||
|
||||
/**
|
||||
* dvd_close: close the DVD device and clean up the library.
|
||||
*/
|
||||
static int dvd_close ( dvd_handle dev )
|
||||
{
|
||||
int i_ret;
|
||||
|
||||
i_ret = close( dev->i_fd );
|
||||
|
||||
if( i_ret < 0 )
|
||||
{
|
||||
return i_ret;
|
||||
}
|
||||
|
||||
free( dev );
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DVDSetupRead( void )
|
||||
{
|
||||
void * dvdcss_library = NULL;
|
||||
|
||||
if( ( dvdcss_library = dlopen( "libdvdcss.so.1", RTLD_LAZY ) ) )
|
||||
{
|
||||
pf_dvd_open = dlsym( dvdcss_library, "dvdcss_open" );
|
||||
pf_dvd_close = dlsym( dvdcss_library, "dvdcss_close" );
|
||||
pf_dvd_title = dlsym( dvdcss_library, "dvdcss_title" );
|
||||
pf_dvd_seek = dlsym( dvdcss_library, "dvdcss_seek" );
|
||||
pf_dvd_read = dlsym( dvdcss_library, "dvdcss_read" );
|
||||
pf_dvd_readv = dlsym( dvdcss_library, "dvdcss_readv" );
|
||||
pf_dvd_error = dlsym( dvdcss_library, "dvdcss_error" );
|
||||
|
||||
if( pf_dvd_open == NULL || pf_dvd_close == NULL
|
||||
|| pf_dvd_title == NULL || pf_dvd_seek == NULL
|
||||
|| pf_dvd_read == NULL || pf_dvd_readv == NULL
|
||||
|| pf_dvd_error == NULL )
|
||||
{
|
||||
fprintf( stderr, "libdvdread: Missing symbols in libdvdcss.so.1, "
|
||||
"this shouldn't happen !" );
|
||||
dlclose( dvdcss_library );
|
||||
dvdcss_library = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
printf( "libdvdread: Using libdvdcss.so.1 for DVD access\n" );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
fprintf( stderr, "libdvdread: Can't open libdvdcss.so.1: %s.\n",
|
||||
dlerror() );
|
||||
}
|
||||
|
||||
if( !dvdcss_library )
|
||||
{
|
||||
/* Replacement functions */
|
||||
pf_dvd_open = dvd_open;
|
||||
pf_dvd_close = dvd_close;
|
||||
pf_dvd_title = dvd_title;
|
||||
pf_dvd_seek = dvd_seek;
|
||||
pf_dvd_read = dvd_read;
|
||||
pf_dvd_readv = dvd_readv;
|
||||
pf_dvd_error = dvd_error;
|
||||
}
|
||||
}
|
||||
#else
|
||||
void DVDSetupRead( void )
|
||||
{
|
||||
pf_dvd_open = dvdcss_open;
|
||||
pf_dvd_close = dvdcss_close;
|
||||
pf_dvd_title = dvdcss_title;
|
||||
pf_dvd_seek = dvdcss_seek;
|
||||
pf_dvd_read = dvdcss_read;
|
||||
pf_dvd_readv = dvdcss_readv;
|
||||
pf_dvd_error = dvdcss_error;
|
||||
}
|
||||
#endif
|
64
extras/libdvdread/dvd_setup.h
Normal file
64
extras/libdvdread/dvd_setup.h
Normal file
@ -0,0 +1,64 @@
|
||||
/**
|
||||
* dvd_setup.h: setup functions header.
|
||||
*/
|
||||
|
||||
/* Copyright (C) 2001 VideoLAN
|
||||
* $Id: dvd_setup.h,v 1.1 2002/01/23 03:15:31 stef Exp $
|
||||
*
|
||||
* Authors: Samuel Hocevar <sam@zoy.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
|
||||
*/
|
||||
|
||||
/**
|
||||
* The libdvdcss structure.
|
||||
*/
|
||||
struct dvdcss_s
|
||||
{
|
||||
/* File descriptor */
|
||||
int i_fd;
|
||||
};
|
||||
|
||||
#ifdef GOD_DAMN_DMCA
|
||||
/**
|
||||
* Defines and flags.
|
||||
*/
|
||||
# define DVDCSS_NOFLAGS 0
|
||||
# define DVDCSS_READ_DECRYPT (1 << 0)
|
||||
# define DVDCSS_SEEK_MPEG (1 << 0)
|
||||
# define DVDCSS_SEEK_KEY (1 << 1)
|
||||
|
||||
#else
|
||||
# include <videolan/dvdcss.h>
|
||||
#endif
|
||||
|
||||
typedef struct dvdcss_s* dvd_handle;
|
||||
|
||||
/**
|
||||
* Pointers which will be filled either with dummy functions or
|
||||
* with the dlopen()ed ones.
|
||||
*/
|
||||
dvd_handle (*pf_dvd_open) ( char * );
|
||||
int (*pf_dvd_close) ( dvd_handle );
|
||||
int (*pf_dvd_title) ( dvd_handle, int );
|
||||
int (*pf_dvd_seek) ( dvd_handle, int, int );
|
||||
int (*pf_dvd_read) ( dvd_handle, void *, int, int );
|
||||
int (*pf_dvd_readv) ( dvd_handle, void *, int, int );
|
||||
char * (*pf_dvd_error) ( dvd_handle );
|
||||
|
||||
/**
|
||||
* Setup function accessed by dvd_reader.c
|
||||
*/
|
||||
void DVDSetupRead( void );
|
@ -1,41 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* libdvdcss.h: DVD reading library, exported functions.
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1998-2001 VideoLAN
|
||||
* $Id: dvdcss.h,v 1.1 2001/11/25 05:04:38 stef Exp $
|
||||
*
|
||||
* Authors: Stéphane Borel <stef@via.ecp.fr>
|
||||
* Samuel Hocevar <sam@zoy.org>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
|
||||
*****************************************************************************/
|
||||
|
||||
/*****************************************************************************
|
||||
* The libdvdcss structure
|
||||
*****************************************************************************/
|
||||
typedef struct dvdcss_s* dvdcss_handle;
|
||||
|
||||
/*****************************************************************************
|
||||
* Flags
|
||||
*****************************************************************************/
|
||||
#define DVDCSS_NOFLAGS 0
|
||||
|
||||
#define DVDCSS_INIT_QUIET (1 << 0)
|
||||
#define DVDCSS_INIT_DEBUG (1 << 1)
|
||||
|
||||
#define DVDCSS_READ_DECRYPT (1 << 0)
|
||||
|
||||
#define DVDCSS_BLOCK_SIZE 2048
|
||||
|
@ -1,960 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* dvdread.c: replacement for dvd_reader.c that always takes dvdcss functions
|
||||
* (hard-linked) and adds a readv call function to tha API.
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 Billy Biggs <vektor@dumbterm.net>.
|
||||
* $Id: dvdread.c,v 1.3 2002/01/15 05:22:21 stef Exp $
|
||||
*
|
||||
* Author: Billy Biggs <vektor@dumbterm.net>
|
||||
* Stéphane Borel <stef@via.ecp.fr>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/uio.h> /* readv() */
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <dlfcn.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__)
|
||||
#define SYS_BSD 1
|
||||
#endif
|
||||
|
||||
#if defined(__sun)
|
||||
#include <sys/mnttab.h>
|
||||
#elif defined(SYS_BSD)
|
||||
#include <fstab.h>
|
||||
#elif defined(__linux__)
|
||||
#include <mntent.h>
|
||||
#endif
|
||||
|
||||
#if defined(SYS_BSD)
|
||||
typedef off_t off64_t;
|
||||
#define lseek64 lseek
|
||||
#define stat64 stat
|
||||
#endif
|
||||
|
||||
#include "dvd_udf.h"
|
||||
#include "dvd_reader.h"
|
||||
|
||||
#include "../libdvdcss/videolan/dvdcss.h"
|
||||
|
||||
struct dvd_reader_s {
|
||||
/* Basic information. */
|
||||
int isImageFile;
|
||||
|
||||
/* Information required for an image file. */
|
||||
dvdcss_handle dev;
|
||||
int init_keys;
|
||||
int fd;
|
||||
|
||||
/* Information required for a directory path drive. */
|
||||
char *path_root;
|
||||
};
|
||||
|
||||
struct dvd_file_s {
|
||||
/* Basic information. */
|
||||
dvd_reader_t *dvd;
|
||||
|
||||
/* Information required for an image file. */
|
||||
uint32_t lb_start;
|
||||
uint32_t seek_pos;
|
||||
|
||||
/* Information required for a directory path drive. */
|
||||
dvdcss_handle title_devs[9];
|
||||
size_t title_sizes[ 9 ];
|
||||
int title_fds[ 9 ];
|
||||
|
||||
/* Calculated at open-time, size in blocks. */
|
||||
ssize_t filesize;
|
||||
};
|
||||
|
||||
/**
|
||||
* Open a DVD image or block device file.
|
||||
*/
|
||||
static dvd_reader_t *DVDOpenImageFile( const char *location )
|
||||
{
|
||||
dvd_reader_t *dvd;
|
||||
dvdcss_handle dev = 0;
|
||||
int fd = -1;
|
||||
|
||||
dev = dvdcss_open( (char *) location );
|
||||
if( !dev ) {
|
||||
fprintf( stderr, "libdvdread: Can't open %s for reading.\n",
|
||||
location );
|
||||
return 0;
|
||||
}
|
||||
|
||||
dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) );
|
||||
if( !dvd ) return 0;
|
||||
dvd->isImageFile = 1;
|
||||
dvd->dev = dev;
|
||||
dvd->init_keys = 0;
|
||||
dvd->fd = fd;
|
||||
dvd->path_root = 0;
|
||||
|
||||
return dvd;
|
||||
}
|
||||
|
||||
static dvd_reader_t *DVDOpenPath( const char *path_root )
|
||||
{
|
||||
dvd_reader_t *dvd;
|
||||
|
||||
fprintf(stderr, "libdvdread: opening %s as folder\n", path_root );
|
||||
dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) );
|
||||
if( !dvd ) return 0;
|
||||
dvd->isImageFile = 0;
|
||||
dvd->dev = 0;
|
||||
dvd->init_keys = 0;
|
||||
dvd->fd = -1;
|
||||
dvd->path_root = strdup( path_root );
|
||||
|
||||
return dvd;
|
||||
}
|
||||
|
||||
#if defined(__sun)
|
||||
/* /dev/rdsk/c0t6d0s0 (link to /devices/...)
|
||||
/vol/dev/rdsk/c0t6d0/??
|
||||
/vol/rdsk/<name> */
|
||||
static char *sun_block2char( const char *path )
|
||||
{
|
||||
char *new_path;
|
||||
|
||||
/* Must contain "/dsk/" */
|
||||
if( !strstr( path, "/dsk/" ) ) return (char *) strdup( path );
|
||||
|
||||
/* Replace "/dsk/" with "/rdsk/" */
|
||||
new_path = malloc( strlen(path) + 2 );
|
||||
strcpy( new_path, path );
|
||||
strcpy( strstr( new_path, "/dsk/" ), "" );
|
||||
strcat( new_path, "/rdsk/" );
|
||||
strcat( new_path, strstr( path, "/dsk/" ) + strlen( "/dsk/" ) );
|
||||
|
||||
return new_path;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SYS_BSD)
|
||||
/* FreeBSD /dev/(r)(a)cd0 (a is for atapi, should work without r)
|
||||
OpenBSD /dev/rcd0c
|
||||
NetBSD /dev/rcd0d or /dev/rcd0c (for non x86)
|
||||
BSD/OS /dev/sr0 (if not mounted) or /dev/rsr0 */
|
||||
static char *bsd_block2char( const char *path )
|
||||
{
|
||||
char *new_path;
|
||||
|
||||
/* If it doesn't start with "/dev/" or does start with "/dev/r" exit */
|
||||
if( !strncmp( path, "/dev/", 5 ) || strncmp( path, "/dev/r", 6 ) )
|
||||
return (char *) strdup( path );
|
||||
|
||||
/* Replace "/dev/" with "/dev/r" */
|
||||
new_path = malloc( strlen(path) + 2 );
|
||||
strcpy( new_path, "/dev/r" );
|
||||
strcat( new_path, path + strlen( "/dev/" ) );
|
||||
|
||||
return new_path;
|
||||
}
|
||||
#endif
|
||||
|
||||
dvd_reader_t *DVDOpen( const char *path )
|
||||
{
|
||||
struct stat64 fileinfo;
|
||||
int ret;
|
||||
|
||||
if( !path ) return 0;
|
||||
|
||||
ret = stat64( path, &fileinfo );
|
||||
if( ret < 0 ) {
|
||||
/* If we can't stat the file, give up */
|
||||
fprintf( stderr, "libdvdread: Can't stat %s\n", path );
|
||||
perror("");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* First check if this is a block/char device or a file*/
|
||||
if( S_ISBLK( fileinfo.st_mode ) ||
|
||||
S_ISCHR( fileinfo.st_mode ) ||
|
||||
S_ISREG( fileinfo.st_mode ) ) {
|
||||
|
||||
/**
|
||||
* Block devices and regular files are assumed to be DVD-Video images.
|
||||
*/
|
||||
#if defined(__sun)
|
||||
return DVDOpenImageFile( sun_block2char( path ) );
|
||||
#elif defined(SYS_BSD)
|
||||
return DVDOpenImageFile( bsd_block2char( path ) );
|
||||
#else
|
||||
return DVDOpenImageFile( path );
|
||||
#endif
|
||||
|
||||
} else if( S_ISDIR( fileinfo.st_mode ) ) {
|
||||
dvd_reader_t *auth_drive = 0;
|
||||
char *path_copy;
|
||||
#if defined(SYS_BSD)
|
||||
struct fstab* fe;
|
||||
#elif defined(__sun) || defined(__linux__)
|
||||
FILE *mntfile;
|
||||
#endif
|
||||
|
||||
/* XXX: We should scream real loud here. */
|
||||
if( !(path_copy = strdup( path ) ) ) return 0;
|
||||
|
||||
/* Resolve any symlinks and get the absolut dir name. */
|
||||
{
|
||||
char *new_path;
|
||||
int cdir = open( ".", O_RDONLY );
|
||||
|
||||
if( cdir >= 0 ) {
|
||||
chdir( path_copy );
|
||||
new_path = getcwd( NULL, PATH_MAX );
|
||||
fchdir( cdir );
|
||||
close( cdir );
|
||||
if( new_path ) {
|
||||
free( path_copy );
|
||||
path_copy = new_path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If we're being asked to open a directory, check if that directory
|
||||
* is the mountpoint for a DVD-ROM which we can use instead.
|
||||
*/
|
||||
|
||||
if( strlen( path_copy ) > 1 ) {
|
||||
if( path[ strlen( path_copy ) - 1 ] == '/' )
|
||||
path_copy[ strlen( path_copy ) - 1 ] = '\0';
|
||||
}
|
||||
|
||||
if( strlen( path_copy ) > 9 ) {
|
||||
if( !strcasecmp( &(path_copy[ strlen( path_copy ) - 9 ]),
|
||||
"/video_ts" ) ) {
|
||||
path_copy[ strlen( path_copy ) - 9 ] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(SYS_BSD)
|
||||
if( ( fe = getfsfile( path_copy ) ) ) {
|
||||
char *dev_name = bsd_block2char( fe->fs_spec );
|
||||
fprintf( stderr,
|
||||
"libdvdread: Attempting to use device %s"
|
||||
" mounted on %s for CSS authentication\n",
|
||||
dev_name,
|
||||
fe->fs_file );
|
||||
auth_drive = DVDOpenImageFile( dev_name );
|
||||
free( dev_name );
|
||||
}
|
||||
#elif defined(__sun)
|
||||
mntfile = fopen( MNTTAB, "r" );
|
||||
if( mntfile ) {
|
||||
struct mnttab mp;
|
||||
int res;
|
||||
|
||||
while( ( res = getmntent( mntfile, &mp ) ) != -1 ) {
|
||||
if( res == 0 && !strcmp( mp.mnt_mountp, path_copy ) ) {
|
||||
char *dev_name = sun_block2char( mp.mnt_special );
|
||||
fprintf( stderr,
|
||||
"libdvdread: Attempting to use device %s"
|
||||
" mounted on %s for CSS authentication\n",
|
||||
dev_name,
|
||||
mp.mnt_mountp );
|
||||
auth_drive = DVDOpenImageFile( dev_name );
|
||||
free( dev_name );
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose( mntfile );
|
||||
}
|
||||
#elif defined(__linux__)
|
||||
mntfile = fopen( MOUNTED, "r" );
|
||||
if( mntfile ) {
|
||||
struct mntent *me;
|
||||
|
||||
while( ( me = getmntent( mntfile ) ) ) {
|
||||
if( !strcmp( me->mnt_dir, path_copy ) ) {
|
||||
fprintf( stderr,
|
||||
"libdvdread: Attempting to use device %s"
|
||||
" mounted on %s for CSS authentication\n",
|
||||
me->mnt_fsname,
|
||||
me->mnt_dir );
|
||||
auth_drive = DVDOpenImageFile( me->mnt_fsname );
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose( mntfile );
|
||||
}
|
||||
#endif
|
||||
if( !auth_drive ) {
|
||||
fprintf( stderr, "libdvdread: Device inaccessible, "
|
||||
"CSS authentication not available.\n" );
|
||||
}
|
||||
|
||||
free( path_copy );
|
||||
|
||||
/**
|
||||
* If we've opened a drive, just use that.
|
||||
*/
|
||||
if( auth_drive ) return auth_drive;
|
||||
|
||||
/**
|
||||
* Otherwise, we now try to open the directory tree instead.
|
||||
*/
|
||||
fprintf( stderr, "libdvdread: Using normal filesystem access.\n" );
|
||||
return DVDOpenPath( path );
|
||||
}
|
||||
|
||||
/* If it's none of the above, screw it. */
|
||||
fprintf( stderr, "libdvdread: Could not open %s\n", path );
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DVDClose( dvd_reader_t *dvd )
|
||||
{
|
||||
if( dvd ) {
|
||||
if( dvd->dev ) dvdcss_close( dvd->dev );
|
||||
if( dvd->fd >= 0 ) close( dvd->fd );
|
||||
if( dvd->path_root ) free( dvd->path_root );
|
||||
free( dvd );
|
||||
dvd = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open an unencrypted file on a DVD image file.
|
||||
*/
|
||||
static dvd_file_t *DVDOpenFileUDF( dvd_reader_t *dvd, char *filename )
|
||||
{
|
||||
uint32_t start, len;
|
||||
dvd_file_t *dvd_file;
|
||||
|
||||
start = UDFFindFile( dvd, filename, &len );
|
||||
if( !start ) return 0;
|
||||
|
||||
fprintf( stderr, "libdvdread: opening %s as image\n", filename );
|
||||
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
|
||||
if( !dvd_file ) return 0;
|
||||
dvd_file->dvd = dvd;
|
||||
dvd_file->lb_start = start;
|
||||
dvd_file->seek_pos = 0;
|
||||
memset( dvd_file->title_devs, -1, sizeof( dvd_file->title_devs ) );
|
||||
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) );
|
||||
dvd_file->filesize = len / DVD_VIDEO_LB_LEN;
|
||||
|
||||
return dvd_file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for <file> in directory <path>, ignoring case.
|
||||
* Returns 0 and full filename in <filename>.
|
||||
* or -1 on file not found.
|
||||
* or -2 on path not found.
|
||||
*/
|
||||
static int findDirFile( const char *path, const char *file, char *filename )
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
|
||||
dir = opendir( path );
|
||||
if( !dir ) return -2;
|
||||
|
||||
while( ( ent = readdir( dir ) ) != NULL ) {
|
||||
if( !strcasecmp( ent->d_name, file ) ) {
|
||||
sprintf( filename, "%s%s%s", path,
|
||||
( ( path[ strlen( path ) - 1 ] == '/' ) ? "" : "/" ),
|
||||
ent->d_name );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int findDVDFile( dvd_reader_t *dvd, const char *file, char *filename )
|
||||
{
|
||||
char video_path[ PATH_MAX + 1 ];
|
||||
const char *nodirfile;
|
||||
int ret;
|
||||
|
||||
/* Strip off the directory for our search */
|
||||
if( !strncasecmp( "/VIDEO_TS/", file, 10 ) ) {
|
||||
nodirfile = &(file[ 10 ]);
|
||||
} else {
|
||||
nodirfile = file;
|
||||
}
|
||||
|
||||
ret = findDirFile( dvd->path_root, nodirfile, filename );
|
||||
if( ret < 0 ) {
|
||||
/* Try also with adding the path, just in case. */
|
||||
sprintf( video_path, "%s/VIDEO_TS/", dvd->path_root );
|
||||
ret = findDirFile( video_path, nodirfile, filename );
|
||||
if( ret < 0 ) {
|
||||
/* Try with the path, but in lower case. */
|
||||
sprintf( video_path, "%s/video_ts/", dvd->path_root );
|
||||
ret = findDirFile( video_path, nodirfile, filename );
|
||||
if( ret < 0 ) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open an unencrypted file from a DVD directory tree.
|
||||
*/
|
||||
static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename )
|
||||
{
|
||||
char full_path[ PATH_MAX + 1 ];
|
||||
dvd_file_t *dvd_file;
|
||||
struct stat fileinfo;
|
||||
int fd;
|
||||
|
||||
/* Get the full path of the file. */
|
||||
if( !findDVDFile( dvd, filename, full_path ) ) return 0;
|
||||
|
||||
fprintf( stderr, "libdvdread: opening %s as file\n", full_path );
|
||||
fd = open( full_path, O_RDONLY );
|
||||
if( fd < 0 ) return 0;
|
||||
|
||||
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
|
||||
if( !dvd_file ) return 0;
|
||||
dvd_file->dvd = dvd;
|
||||
dvd_file->lb_start = 0;
|
||||
dvd_file->seek_pos = 0;
|
||||
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
|
||||
memset( dvd_file->title_devs, -1, sizeof( dvd_file->title_devs ) );
|
||||
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) );
|
||||
dvd_file->filesize = 0;
|
||||
|
||||
if( stat( full_path, &fileinfo ) < 0 ) {
|
||||
fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
|
||||
free( dvd_file );
|
||||
return 0;
|
||||
}
|
||||
dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
|
||||
dvd_file->title_fds[ 0 ] = fd;
|
||||
dvd_file->filesize = dvd_file->title_sizes[ 0 ];
|
||||
|
||||
return dvd_file;
|
||||
}
|
||||
|
||||
static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd,
|
||||
int title, int menu )
|
||||
{
|
||||
char filename[ MAX_UDF_FILE_NAME_LEN ];
|
||||
uint32_t start, len;
|
||||
dvd_file_t *dvd_file;
|
||||
|
||||
fprintf( stderr, "libdvdread: opening VOB as image\n" );
|
||||
if( title == 0 ) {
|
||||
sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" );
|
||||
} else {
|
||||
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, menu ? 0 : 1 );
|
||||
}
|
||||
start = UDFFindFile( dvd, filename, &len );
|
||||
if( start == 0 ) return 0;
|
||||
|
||||
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
|
||||
if( !dvd_file ) return 0;
|
||||
dvd_file->dvd = dvd;
|
||||
dvd_file->lb_start = start;
|
||||
dvd_file->seek_pos = 0;
|
||||
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
|
||||
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) );
|
||||
dvd_file->filesize = len / DVD_VIDEO_LB_LEN;
|
||||
|
||||
/* Calculate the complete file size for every file in the VOBS */
|
||||
if( !menu ) {
|
||||
int cur;
|
||||
|
||||
for( cur = 2; cur < 10; cur++ ) {
|
||||
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, cur );
|
||||
if( !UDFFindFile( dvd, filename, &len ) ) break;
|
||||
dvd_file->filesize += len / DVD_VIDEO_LB_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
if( dvdcss_seek( dvd_file->dvd->dev, (int)start, DVDCSS_SEEK_KEY ) < 0 ) {
|
||||
fprintf( stderr, "libdvdread: Error cracking CSS key for %s\n",
|
||||
filename );
|
||||
}
|
||||
|
||||
return dvd_file;
|
||||
}
|
||||
|
||||
static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd,
|
||||
int title, int menu )
|
||||
{
|
||||
char filename[ MAX_UDF_FILE_NAME_LEN ];
|
||||
char full_path[ PATH_MAX + 1 ];
|
||||
struct stat fileinfo;
|
||||
dvd_file_t *dvd_file;
|
||||
int i;
|
||||
|
||||
fprintf( stderr, "libdvdread: opening VOB as file\n" );
|
||||
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
|
||||
if( !dvd_file ) return 0;
|
||||
dvd_file->dvd = dvd;
|
||||
dvd_file->lb_start = 0;
|
||||
dvd_file->seek_pos = 0;
|
||||
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
|
||||
memset( dvd_file->title_devs, -1, sizeof( dvd_file->title_devs ) );
|
||||
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) );
|
||||
dvd_file->filesize = 0;
|
||||
|
||||
if( menu ) {
|
||||
int fd;
|
||||
|
||||
if( title == 0 ) {
|
||||
sprintf( filename, "VIDEO_TS.VOB" );
|
||||
} else {
|
||||
sprintf( filename, "VTS_%02i_0.VOB", title );
|
||||
}
|
||||
if( !findDVDFile( dvd, filename, full_path ) ) {
|
||||
free( dvd_file );
|
||||
return 0;
|
||||
}
|
||||
|
||||
fd = open( full_path, O_RDONLY );
|
||||
if( fd < 0 ) {
|
||||
free( dvd_file );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( stat( full_path, &fileinfo ) < 0 ) {
|
||||
fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
|
||||
free( dvd_file );
|
||||
return 0;
|
||||
}
|
||||
dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
|
||||
dvd_file->title_fds[ 0 ] = fd;
|
||||
dvd_file->title_devs[ 0 ] = dvdcss_open( full_path );
|
||||
dvdcss_title( dvd_file->title_devs[0], 0 );
|
||||
dvd_file->filesize = dvd_file->title_sizes[ 0 ];
|
||||
|
||||
} else {
|
||||
for( i = 0; i < 9; ++i ) {
|
||||
|
||||
sprintf( filename, "VTS_%02i_%i.VOB", title, i + 1 );
|
||||
if( !findDVDFile( dvd, filename, full_path ) ) {
|
||||
break;
|
||||
}
|
||||
|
||||
if( stat( full_path, &fileinfo ) < 0 ) {
|
||||
fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
|
||||
break;
|
||||
}
|
||||
|
||||
dvd_file->title_sizes[ i ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
|
||||
dvd_file->title_fds[ i ] = open( full_path, O_RDONLY );
|
||||
dvd_file->title_devs[ i ] = dvdcss_open( full_path );
|
||||
dvdcss_title( dvd_file->title_devs[i], 0 );
|
||||
dvd_file->filesize += dvd_file->title_sizes[ i ];
|
||||
}
|
||||
if( !(dvd_file->title_sizes[ 0 ]) ) {
|
||||
free( dvd_file );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return dvd_file;
|
||||
}
|
||||
|
||||
dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum,
|
||||
dvd_read_domain_t domain )
|
||||
{
|
||||
char filename[ MAX_UDF_FILE_NAME_LEN ];
|
||||
|
||||
switch( domain ) {
|
||||
case DVD_READ_INFO_FILE:
|
||||
if( titlenum == 0 ) {
|
||||
sprintf( filename, "/VIDEO_TS/VIDEO_TS.IFO" );
|
||||
} else {
|
||||
sprintf( filename, "/VIDEO_TS/VTS_%02i_0.IFO", titlenum );
|
||||
}
|
||||
break;
|
||||
case DVD_READ_INFO_BACKUP_FILE:
|
||||
if( titlenum == 0 ) {
|
||||
sprintf( filename, "/VIDEO_TS/VIDEO_TS.BUP" );
|
||||
} else {
|
||||
sprintf( filename, "/VIDEO_TS/VTS_%02i_0.BUP", titlenum );
|
||||
}
|
||||
break;
|
||||
case DVD_READ_MENU_VOBS:
|
||||
if( dvd->isImageFile ) {
|
||||
return DVDOpenVOBUDF( dvd, titlenum, 1 );
|
||||
} else {
|
||||
return DVDOpenVOBPath( dvd, titlenum, 1 );
|
||||
}
|
||||
break;
|
||||
case DVD_READ_TITLE_VOBS:
|
||||
if( titlenum == 0 ) return 0;
|
||||
if( dvd->isImageFile ) {
|
||||
return DVDOpenVOBUDF( dvd, titlenum, 0 );
|
||||
} else {
|
||||
return DVDOpenVOBPath( dvd, titlenum, 0 );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf( stderr, "libdvdread: Invalid domain for file open.\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( dvd->isImageFile ) {
|
||||
return DVDOpenFileUDF( dvd, filename );
|
||||
} else {
|
||||
return DVDOpenFilePath( dvd, filename );
|
||||
}
|
||||
}
|
||||
|
||||
void DVDCloseFile( dvd_file_t *dvd_file )
|
||||
{
|
||||
int i;
|
||||
|
||||
if( dvd_file ) {
|
||||
if( !dvd_file->dvd->isImageFile ) {
|
||||
for( i = 0; i < 9; ++i ) {
|
||||
if( dvd_file->title_fds[ i ] >= 0 )
|
||||
{
|
||||
close( dvd_file->title_fds[ i ] );
|
||||
dvdcss_close( dvd_file->title_devs[i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free( dvd_file );
|
||||
dvd_file = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t DVDReadLBUDF( dvd_reader_t *device, uint32_t lb_number,
|
||||
size_t block_count, unsigned char *data,
|
||||
int encrypted )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if( !device->dev ) {
|
||||
fprintf( stderr, "libdvdread: Fatal error in block read.\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = dvdcss_seek( device->dev, (int) lb_number, DVDCSS_NOFLAGS );
|
||||
if( ret != (int) lb_number ) {
|
||||
fprintf( stderr, "libdvdread: Can't seek to block %u\n",
|
||||
lb_number );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int64_t) ( dvdcss_read( device->dev, (char *) data,
|
||||
(int) block_count, encrypted )
|
||||
* (uint64_t) DVD_VIDEO_LB_LEN );
|
||||
}
|
||||
|
||||
static int64_t DVDReadBlocksUDF( dvd_file_t *dvd_file, uint32_t offset,
|
||||
size_t block_count, unsigned char *data )
|
||||
{
|
||||
return DVDReadLBUDF( dvd_file->dvd, dvd_file->lb_start + offset,
|
||||
block_count, data, DVDCSS_READ_DECRYPT );
|
||||
}
|
||||
|
||||
static int64_t DVDReadBlocksPath( dvd_file_t *dvd_file, size_t offset,
|
||||
size_t block_count, unsigned char *data )
|
||||
{
|
||||
int i;
|
||||
ssize_t ret, ret2;
|
||||
off64_t off;
|
||||
|
||||
ret = 0;
|
||||
ret2 = 0;
|
||||
for( i = 0; i < 9; ++i ) {
|
||||
if( !dvd_file->title_sizes[ i ] ) return 0;
|
||||
|
||||
if( offset < dvd_file->title_sizes[ i ] ) {
|
||||
if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] ) {
|
||||
off = lseek64( dvd_file->title_fds[ i ],
|
||||
offset * (int64_t) DVD_VIDEO_LB_LEN, SEEK_SET );
|
||||
if( off != ( offset * (int64_t) DVD_VIDEO_LB_LEN ) ) {
|
||||
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
|
||||
offset );
|
||||
return 0;
|
||||
}
|
||||
ret = read( dvd_file->title_fds[ i ], data,
|
||||
block_count * DVD_VIDEO_LB_LEN );
|
||||
break;
|
||||
} else {
|
||||
size_t part1_size
|
||||
= ( dvd_file->title_sizes[ i ] - offset ) * DVD_VIDEO_LB_LEN;
|
||||
/* FIXME: Really needs to be a while loop.
|
||||
(This is only true if you try and read >1GB at a time) */
|
||||
|
||||
/* Read part 1 */
|
||||
off = lseek64( dvd_file->title_fds[ i ],
|
||||
offset * (int64_t) DVD_VIDEO_LB_LEN, SEEK_SET );
|
||||
if( off != ( offset * (int64_t) DVD_VIDEO_LB_LEN ) ) {
|
||||
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
|
||||
offset );
|
||||
return 0;
|
||||
}
|
||||
ret = read( dvd_file->title_fds[ i ], data, part1_size );
|
||||
if( ret < 0 ) return ret;
|
||||
/* FIXME: This is wrong if i is the last file in the set.
|
||||
also error from this read will not show in ret. */
|
||||
|
||||
/* Read part 2 */
|
||||
lseek64( dvd_file->title_fds[ i + 1 ], (off64_t)0, SEEK_SET );
|
||||
ret2 = read( dvd_file->title_fds[ i + 1 ], data + part1_size,
|
||||
block_count * DVD_VIDEO_LB_LEN - part1_size );
|
||||
if( ret2 < 0 ) return ret2;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
offset -= dvd_file->title_sizes[ i ];
|
||||
}
|
||||
}
|
||||
|
||||
return ( (int64_t) ret + (int64_t) ret2 );
|
||||
}
|
||||
|
||||
/* These are broken for some cases reading more than 2Gb at a time. */
|
||||
ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset,
|
||||
size_t block_count, unsigned char *data )
|
||||
{
|
||||
int64_t ret;
|
||||
|
||||
if( dvd_file->dvd->isImageFile ) {
|
||||
ret = DVDReadBlocksUDF( dvd_file, (uint32_t)offset,
|
||||
block_count, data );
|
||||
} else {
|
||||
ret = DVDReadBlocksPath( dvd_file, (size_t) offset,
|
||||
block_count, data );
|
||||
}
|
||||
if( ret <= 0 ) {
|
||||
return (ssize_t) ret;
|
||||
}
|
||||
{
|
||||
ssize_t sret = (ssize_t) (ret / (int64_t)DVD_VIDEO_LB_LEN );
|
||||
if( sret == 0 ) {
|
||||
fprintf(stderr, "libdvdread: DVDReadBlocks got %d bytes\n", (int)ret );
|
||||
}
|
||||
return sret;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t DVDFileSeek( dvd_file_t *dvd_file, int32_t offset )
|
||||
{
|
||||
if( dvd_file->dvd->isImageFile ) {
|
||||
dvd_file->seek_pos = (uint32_t) offset;
|
||||
return offset;
|
||||
} else {
|
||||
return (int32_t) ( lseek( dvd_file->title_fds[ 0 ],
|
||||
(off_t) offset, SEEK_SET ) );
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t DVDReadBytesUDF( dvd_file_t *dvd_file, void *data,
|
||||
size_t byte_size )
|
||||
{
|
||||
unsigned char *secbuf;
|
||||
unsigned int numsec, seek_sector, seek_byte;
|
||||
int64_t len;
|
||||
|
||||
seek_sector = dvd_file->seek_pos / DVD_VIDEO_LB_LEN;
|
||||
seek_byte = dvd_file->seek_pos % DVD_VIDEO_LB_LEN;
|
||||
|
||||
numsec = ( ( seek_byte + byte_size ) / DVD_VIDEO_LB_LEN ) + 1;
|
||||
secbuf = (unsigned char *) malloc( numsec * DVD_VIDEO_LB_LEN );
|
||||
if( !secbuf ) {
|
||||
fprintf( stderr, "libdvdread: Can't allocate memory "
|
||||
"for file read!\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = DVDReadLBUDF( dvd_file->dvd, dvd_file->lb_start + seek_sector,
|
||||
numsec, secbuf, DVDCSS_NOFLAGS );
|
||||
if( len != numsec * (int64_t) DVD_VIDEO_LB_LEN ) {
|
||||
free( secbuf );
|
||||
return 0;
|
||||
}
|
||||
|
||||
dvd_file->seek_pos += byte_size;
|
||||
|
||||
memcpy( data, &(secbuf[ seek_byte ]), byte_size );
|
||||
free( secbuf );
|
||||
|
||||
return byte_size;
|
||||
}
|
||||
|
||||
static ssize_t DVDReadBytesPath( dvd_file_t *dvd_file, void *data,
|
||||
size_t byte_size )
|
||||
{
|
||||
return read( dvd_file->title_fds[ 0 ], data, byte_size );
|
||||
}
|
||||
|
||||
ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size )
|
||||
{
|
||||
if( dvd_file->dvd->isImageFile ) {
|
||||
return DVDReadBytesUDF( dvd_file, data, byte_size );
|
||||
} else {
|
||||
return DVDReadBytesPath( dvd_file, data, byte_size );
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t DVDFileSize( dvd_file_t *dvd_file )
|
||||
{
|
||||
return dvd_file->filesize;
|
||||
}
|
||||
|
||||
int64_t DVDReadVLBUDF( dvd_reader_t *device, uint32_t lb_number,
|
||||
size_t block_count, struct iovec * vector,
|
||||
int encrypted )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if( !device->dev ) {
|
||||
fprintf( stderr, "libdvdread: Fatal error in block read.\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = dvdcss_seek( device->dev, (int) lb_number, 0 );
|
||||
if( ret != (int) lb_number ) {
|
||||
fprintf( stderr, "libdvdread: Can't seek to block %u\n",
|
||||
lb_number );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int64_t) ( dvdcss_readv( device->dev, vector,
|
||||
(int)block_count, encrypted )
|
||||
* (uint64_t) DVD_VIDEO_LB_LEN );
|
||||
}
|
||||
|
||||
static int64_t DVDReadVBlocksUDF( dvd_file_t *dvd_file, uint32_t offset,
|
||||
size_t block_count, struct iovec *vector )
|
||||
{
|
||||
return DVDReadVLBUDF( dvd_file->dvd, dvd_file->lb_start + offset,
|
||||
block_count, vector, DVDCSS_READ_DECRYPT );
|
||||
}
|
||||
|
||||
static int64_t DVDReadVBlocksPath( dvd_file_t *dvd_file, size_t offset,
|
||||
size_t block_count, struct iovec *vector )
|
||||
{
|
||||
int i;
|
||||
int ret, ret2;
|
||||
int off;
|
||||
|
||||
ret = 0;
|
||||
ret2 = 0;
|
||||
for( i = 0 ; i < 9 ; ++i )
|
||||
{
|
||||
if( !dvd_file->title_sizes[ i ] )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( offset < dvd_file->title_sizes[ i ] )
|
||||
{
|
||||
if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] )
|
||||
{
|
||||
off = dvdcss_seek( dvd_file->title_devs[ i ],
|
||||
(int)offset, 0 );
|
||||
if( off != (int)offset )
|
||||
{
|
||||
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
|
||||
offset );
|
||||
return 0;
|
||||
}
|
||||
ret = dvdcss_readv( dvd_file->title_devs[ i ], vector,
|
||||
(int)block_count, DVDCSS_READ_DECRYPT );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
int part1_size = dvd_file->title_sizes[ i ] - offset;
|
||||
/* FIXME: Really needs to be a while loop.
|
||||
(This is only true if you try and read >1GB at a time) */
|
||||
|
||||
/* Read part 1 */
|
||||
off = dvdcss_seek( dvd_file->title_devs[ i ], offset, 0 );
|
||||
if( off != offset )
|
||||
{
|
||||
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
|
||||
offset );
|
||||
return 0;
|
||||
}
|
||||
ret = dvdcss_readv( dvd_file->title_devs[ i ], vector,
|
||||
part1_size, DVDCSS_READ_DECRYPT );
|
||||
|
||||
if( ret < 0 ) return ret;
|
||||
/* FIXME: This is wrong if i is the last file in the set.
|
||||
also error from this read will not show in ret. */
|
||||
|
||||
/* Read part 2 */
|
||||
dvdcss_seek( dvd_file->title_devs[ i + 1 ], 0, 0 );
|
||||
ret2 = dvdcss_readv( dvd_file->title_devs[ i + 1 ],
|
||||
vector + part1_size, (int)(block_count - part1_size),
|
||||
DVDCSS_READ_DECRYPT );
|
||||
if( ret2 < 0 ) return ret2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
offset -= dvd_file->title_sizes[ i ];
|
||||
}
|
||||
}
|
||||
|
||||
return ( ret + ret2 ) * (int64_t) DVD_VIDEO_LB_LEN;
|
||||
}
|
||||
|
||||
|
||||
ssize_t DVDReadVBlocks( dvd_file_t *dvd_file, int offset,
|
||||
size_t block_count, struct iovec * vector )
|
||||
{
|
||||
int64_t ret;
|
||||
|
||||
if( dvd_file->dvd->isImageFile )
|
||||
{
|
||||
ret = DVDReadVBlocksUDF( dvd_file, (uint32_t)offset,
|
||||
block_count, vector );
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = DVDReadVBlocksPath( dvd_file, (size_t) offset,
|
||||
block_count, vector );
|
||||
}
|
||||
if( ret <= 0 )
|
||||
{
|
||||
return (ssize_t) ret;
|
||||
}
|
||||
|
||||
{
|
||||
ssize_t sret = (ssize_t) (ret / (int64_t)DVD_VIDEO_LB_LEN );
|
||||
if( sret == 0 )
|
||||
{
|
||||
fprintf(stderr, "libdvdread: DVDReadVBlocks got %d bytes\n", (int)ret );
|
||||
}
|
||||
return sret;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -20,10 +20,8 @@
|
||||
#ifndef IFO_PRINT_H_INCLUDED
|
||||
#define IFO_PRINT_H_INCLUDED
|
||||
|
||||
//#include <dvdread/ifo_types.h>
|
||||
//#include <dvdread/dvd_reader.h>
|
||||
#include "ifo_types.h"
|
||||
#include "dvd_reader.h"
|
||||
#include <dvdread/ifo_types.h>
|
||||
#include <dvdread/dvd_reader.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -20,10 +20,8 @@
|
||||
#ifndef IFO_READ_H_INCLUDED
|
||||
#define IFO_READ_H_INCLUDED
|
||||
|
||||
//#include <dvdread/ifo_types.h>
|
||||
//#include <dvdread/dvd_reader.h>
|
||||
#include "ifo_types.h"
|
||||
#include "dvd_reader.h"
|
||||
#include <dvdread/ifo_types.h>
|
||||
#include <dvdread/dvd_reader.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -21,8 +21,7 @@
|
||||
#define IFO_TYPES_H_INCLUDED
|
||||
|
||||
#include <inttypes.h>
|
||||
//#include <dvdread/dvd_reader.h>
|
||||
#include "dvd_reader.h"
|
||||
#include <dvdread/dvd_reader.h>
|
||||
|
||||
|
||||
#undef ATTRIBUTE_PACKED
|
||||
|
@ -21,8 +21,7 @@
|
||||
#define NAV_PRINT_H_INCLUDED
|
||||
|
||||
#include <stdio.h>
|
||||
//#include <dvdread/nav_types.h>
|
||||
#include "nav_types.h"
|
||||
#include <dvdread/nav_types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -19,8 +19,7 @@
|
||||
#ifndef NAV_READ_H_INCLUDED
|
||||
#define NAV_READ_H_INCLUDED
|
||||
|
||||
//#include <dvdread/nav_types.h>
|
||||
#include "nav_types.h"
|
||||
#include <dvdread/nav_types.h>
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
|
@ -30,8 +30,8 @@
|
||||
#define NAV_TYPES_H_INCLUDED
|
||||
|
||||
#include <inttypes.h>
|
||||
//#include <dvdread/ifo_types.h> // only dvd_time_t, vm_cmd_t and user_ops_t
|
||||
#include "ifo_types.h"
|
||||
#include <dvdread/ifo_types.h> // only dvd_time_t, vm_cmd_t and user_ops_t
|
||||
|
||||
|
||||
#undef ATTRIBUTE_PACKED
|
||||
#undef PRAGMA_PACK_BEGIN
|
||||
|
@ -1 +0,0 @@
|
||||
.dep
|
@ -1,960 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* dvdread.c: replacement for dvd_reader.c that always takes dvdcss functions
|
||||
* (hard-linked) and adds a readv call function to tha API.
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 Billy Biggs <vektor@dumbterm.net>.
|
||||
* $Id: dvdread.c,v 1.2 2002/01/15 05:22:21 stef Exp $
|
||||
*
|
||||
* Author: Billy Biggs <vektor@dumbterm.net>
|
||||
* Stéphane Borel <stef@via.ecp.fr>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
|
||||
*****************************************************************************/
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/stat.h>
|
||||
#include <sys/uio.h> /* readv() */
|
||||
#include <fcntl.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <errno.h>
|
||||
#include <string.h>
|
||||
#include <unistd.h>
|
||||
#include <limits.h>
|
||||
#include <dlfcn.h>
|
||||
#include <dirent.h>
|
||||
|
||||
#if defined(__FreeBSD__) || defined(__OpenBSD__) || defined(__NetBSD__) || defined(__bsdi__)
|
||||
#define SYS_BSD 1
|
||||
#endif
|
||||
|
||||
#if defined(__sun)
|
||||
#include <sys/mnttab.h>
|
||||
#elif defined(SYS_BSD)
|
||||
#include <fstab.h>
|
||||
#elif defined(__linux__)
|
||||
#include <mntent.h>
|
||||
#endif
|
||||
|
||||
#if defined(SYS_BSD)
|
||||
typedef off_t off64_t;
|
||||
#define lseek64 lseek
|
||||
#define stat64 stat
|
||||
#endif
|
||||
|
||||
#include "dvd_udf.h"
|
||||
#include "dvd_reader.h"
|
||||
|
||||
#include "../libdvdcss/videolan/dvdcss.h"
|
||||
|
||||
struct dvd_reader_s {
|
||||
/* Basic information. */
|
||||
int isImageFile;
|
||||
|
||||
/* Information required for an image file. */
|
||||
dvdcss_handle dev;
|
||||
int init_keys;
|
||||
int fd;
|
||||
|
||||
/* Information required for a directory path drive. */
|
||||
char *path_root;
|
||||
};
|
||||
|
||||
struct dvd_file_s {
|
||||
/* Basic information. */
|
||||
dvd_reader_t *dvd;
|
||||
|
||||
/* Information required for an image file. */
|
||||
uint32_t lb_start;
|
||||
uint32_t seek_pos;
|
||||
|
||||
/* Information required for a directory path drive. */
|
||||
dvdcss_handle title_devs[9];
|
||||
size_t title_sizes[ 9 ];
|
||||
int title_fds[ 9 ];
|
||||
|
||||
/* Calculated at open-time, size in blocks. */
|
||||
ssize_t filesize;
|
||||
};
|
||||
|
||||
/**
|
||||
* Open a DVD image or block device file.
|
||||
*/
|
||||
static dvd_reader_t *DVDOpenImageFile( const char *location )
|
||||
{
|
||||
dvd_reader_t *dvd;
|
||||
dvdcss_handle dev = 0;
|
||||
int fd = -1;
|
||||
|
||||
dev = dvdcss_open( (char *) location );
|
||||
if( !dev ) {
|
||||
fprintf( stderr, "libdvdread: Can't open %s for reading.\n",
|
||||
location );
|
||||
return 0;
|
||||
}
|
||||
|
||||
dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) );
|
||||
if( !dvd ) return 0;
|
||||
dvd->isImageFile = 1;
|
||||
dvd->dev = dev;
|
||||
dvd->init_keys = 0;
|
||||
dvd->fd = fd;
|
||||
dvd->path_root = 0;
|
||||
|
||||
return dvd;
|
||||
}
|
||||
|
||||
static dvd_reader_t *DVDOpenPath( const char *path_root )
|
||||
{
|
||||
dvd_reader_t *dvd;
|
||||
|
||||
fprintf(stderr, "libdvdread: opening %s as folder\n", path_root );
|
||||
dvd = (dvd_reader_t *) malloc( sizeof( dvd_reader_t ) );
|
||||
if( !dvd ) return 0;
|
||||
dvd->isImageFile = 0;
|
||||
dvd->dev = 0;
|
||||
dvd->init_keys = 0;
|
||||
dvd->fd = -1;
|
||||
dvd->path_root = strdup( path_root );
|
||||
|
||||
return dvd;
|
||||
}
|
||||
|
||||
#if defined(__sun)
|
||||
/* /dev/rdsk/c0t6d0s0 (link to /devices/...)
|
||||
/vol/dev/rdsk/c0t6d0/??
|
||||
/vol/rdsk/<name> */
|
||||
static char *sun_block2char( const char *path )
|
||||
{
|
||||
char *new_path;
|
||||
|
||||
/* Must contain "/dsk/" */
|
||||
if( !strstr( path, "/dsk/" ) ) return (char *) strdup( path );
|
||||
|
||||
/* Replace "/dsk/" with "/rdsk/" */
|
||||
new_path = malloc( strlen(path) + 2 );
|
||||
strcpy( new_path, path );
|
||||
strcpy( strstr( new_path, "/dsk/" ), "" );
|
||||
strcat( new_path, "/rdsk/" );
|
||||
strcat( new_path, strstr( path, "/dsk/" ) + strlen( "/dsk/" ) );
|
||||
|
||||
return new_path;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if defined(SYS_BSD)
|
||||
/* FreeBSD /dev/(r)(a)cd0 (a is for atapi, should work without r)
|
||||
OpenBSD /dev/rcd0c
|
||||
NetBSD /dev/rcd0d or /dev/rcd0c (for non x86)
|
||||
BSD/OS /dev/sr0 (if not mounted) or /dev/rsr0 */
|
||||
static char *bsd_block2char( const char *path )
|
||||
{
|
||||
char *new_path;
|
||||
|
||||
/* If it doesn't start with "/dev/" or does start with "/dev/r" exit */
|
||||
if( !strncmp( path, "/dev/", 5 ) || strncmp( path, "/dev/r", 6 ) )
|
||||
return (char *) strdup( path );
|
||||
|
||||
/* Replace "/dev/" with "/dev/r" */
|
||||
new_path = malloc( strlen(path) + 2 );
|
||||
strcpy( new_path, "/dev/r" );
|
||||
strcat( new_path, path + strlen( "/dev/" ) );
|
||||
|
||||
return new_path;
|
||||
}
|
||||
#endif
|
||||
|
||||
dvd_reader_t *DVDOpen( const char *path )
|
||||
{
|
||||
struct stat64 fileinfo;
|
||||
int ret;
|
||||
|
||||
if( !path ) return 0;
|
||||
|
||||
ret = stat64( path, &fileinfo );
|
||||
if( ret < 0 ) {
|
||||
/* If we can't stat the file, give up */
|
||||
fprintf( stderr, "libdvdread: Can't stat %s\n", path );
|
||||
perror("");
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* First check if this is a block/char device or a file*/
|
||||
if( S_ISBLK( fileinfo.st_mode ) ||
|
||||
S_ISCHR( fileinfo.st_mode ) ||
|
||||
S_ISREG( fileinfo.st_mode ) ) {
|
||||
|
||||
/**
|
||||
* Block devices and regular files are assumed to be DVD-Video images.
|
||||
*/
|
||||
#if defined(__sun)
|
||||
return DVDOpenImageFile( sun_block2char( path ) );
|
||||
#elif defined(SYS_BSD)
|
||||
return DVDOpenImageFile( bsd_block2char( path ) );
|
||||
#else
|
||||
return DVDOpenImageFile( path );
|
||||
#endif
|
||||
|
||||
} else if( S_ISDIR( fileinfo.st_mode ) ) {
|
||||
dvd_reader_t *auth_drive = 0;
|
||||
char *path_copy;
|
||||
#if defined(SYS_BSD)
|
||||
struct fstab* fe;
|
||||
#elif defined(__sun) || defined(__linux__)
|
||||
FILE *mntfile;
|
||||
#endif
|
||||
|
||||
/* XXX: We should scream real loud here. */
|
||||
if( !(path_copy = strdup( path ) ) ) return 0;
|
||||
|
||||
/* Resolve any symlinks and get the absolut dir name. */
|
||||
{
|
||||
char *new_path;
|
||||
int cdir = open( ".", O_RDONLY );
|
||||
|
||||
if( cdir >= 0 ) {
|
||||
chdir( path_copy );
|
||||
new_path = getcwd( NULL, PATH_MAX );
|
||||
fchdir( cdir );
|
||||
close( cdir );
|
||||
if( new_path ) {
|
||||
free( path_copy );
|
||||
path_copy = new_path;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* If we're being asked to open a directory, check if that directory
|
||||
* is the mountpoint for a DVD-ROM which we can use instead.
|
||||
*/
|
||||
|
||||
if( strlen( path_copy ) > 1 ) {
|
||||
if( path[ strlen( path_copy ) - 1 ] == '/' )
|
||||
path_copy[ strlen( path_copy ) - 1 ] = '\0';
|
||||
}
|
||||
|
||||
if( strlen( path_copy ) > 9 ) {
|
||||
if( !strcasecmp( &(path_copy[ strlen( path_copy ) - 9 ]),
|
||||
"/video_ts" ) ) {
|
||||
path_copy[ strlen( path_copy ) - 9 ] = '\0';
|
||||
}
|
||||
}
|
||||
|
||||
#if defined(SYS_BSD)
|
||||
if( ( fe = getfsfile( path_copy ) ) ) {
|
||||
char *dev_name = bsd_block2char( fe->fs_spec );
|
||||
fprintf( stderr,
|
||||
"libdvdread: Attempting to use device %s"
|
||||
" mounted on %s for CSS authentication\n",
|
||||
dev_name,
|
||||
fe->fs_file );
|
||||
auth_drive = DVDOpenImageFile( dev_name );
|
||||
free( dev_name );
|
||||
}
|
||||
#elif defined(__sun)
|
||||
mntfile = fopen( MNTTAB, "r" );
|
||||
if( mntfile ) {
|
||||
struct mnttab mp;
|
||||
int res;
|
||||
|
||||
while( ( res = getmntent( mntfile, &mp ) ) != -1 ) {
|
||||
if( res == 0 && !strcmp( mp.mnt_mountp, path_copy ) ) {
|
||||
char *dev_name = sun_block2char( mp.mnt_special );
|
||||
fprintf( stderr,
|
||||
"libdvdread: Attempting to use device %s"
|
||||
" mounted on %s for CSS authentication\n",
|
||||
dev_name,
|
||||
mp.mnt_mountp );
|
||||
auth_drive = DVDOpenImageFile( dev_name );
|
||||
free( dev_name );
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose( mntfile );
|
||||
}
|
||||
#elif defined(__linux__)
|
||||
mntfile = fopen( MOUNTED, "r" );
|
||||
if( mntfile ) {
|
||||
struct mntent *me;
|
||||
|
||||
while( ( me = getmntent( mntfile ) ) ) {
|
||||
if( !strcmp( me->mnt_dir, path_copy ) ) {
|
||||
fprintf( stderr,
|
||||
"libdvdread: Attempting to use device %s"
|
||||
" mounted on %s for CSS authentication\n",
|
||||
me->mnt_fsname,
|
||||
me->mnt_dir );
|
||||
auth_drive = DVDOpenImageFile( me->mnt_fsname );
|
||||
break;
|
||||
}
|
||||
}
|
||||
fclose( mntfile );
|
||||
}
|
||||
#endif
|
||||
if( !auth_drive ) {
|
||||
fprintf( stderr, "libdvdread: Device inaccessible, "
|
||||
"CSS authentication not available.\n" );
|
||||
}
|
||||
|
||||
free( path_copy );
|
||||
|
||||
/**
|
||||
* If we've opened a drive, just use that.
|
||||
*/
|
||||
if( auth_drive ) return auth_drive;
|
||||
|
||||
/**
|
||||
* Otherwise, we now try to open the directory tree instead.
|
||||
*/
|
||||
fprintf( stderr, "libdvdread: Using normal filesystem access.\n" );
|
||||
return DVDOpenPath( path );
|
||||
}
|
||||
|
||||
/* If it's none of the above, screw it. */
|
||||
fprintf( stderr, "libdvdread: Could not open %s\n", path );
|
||||
return 0;
|
||||
}
|
||||
|
||||
void DVDClose( dvd_reader_t *dvd )
|
||||
{
|
||||
if( dvd ) {
|
||||
if( dvd->dev ) dvdcss_close( dvd->dev );
|
||||
if( dvd->fd >= 0 ) close( dvd->fd );
|
||||
if( dvd->path_root ) free( dvd->path_root );
|
||||
free( dvd );
|
||||
dvd = 0;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Open an unencrypted file on a DVD image file.
|
||||
*/
|
||||
static dvd_file_t *DVDOpenFileUDF( dvd_reader_t *dvd, char *filename )
|
||||
{
|
||||
uint32_t start, len;
|
||||
dvd_file_t *dvd_file;
|
||||
|
||||
start = UDFFindFile( dvd, filename, &len );
|
||||
if( !start ) return 0;
|
||||
|
||||
fprintf( stderr, "libdvdread: opening %s as image\n", filename );
|
||||
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
|
||||
if( !dvd_file ) return 0;
|
||||
dvd_file->dvd = dvd;
|
||||
dvd_file->lb_start = start;
|
||||
dvd_file->seek_pos = 0;
|
||||
memset( dvd_file->title_devs, -1, sizeof( dvd_file->title_devs ) );
|
||||
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) );
|
||||
dvd_file->filesize = len / DVD_VIDEO_LB_LEN;
|
||||
|
||||
return dvd_file;
|
||||
}
|
||||
|
||||
/**
|
||||
* Searches for <file> in directory <path>, ignoring case.
|
||||
* Returns 0 and full filename in <filename>.
|
||||
* or -1 on file not found.
|
||||
* or -2 on path not found.
|
||||
*/
|
||||
static int findDirFile( const char *path, const char *file, char *filename )
|
||||
{
|
||||
DIR *dir;
|
||||
struct dirent *ent;
|
||||
|
||||
dir = opendir( path );
|
||||
if( !dir ) return -2;
|
||||
|
||||
while( ( ent = readdir( dir ) ) != NULL ) {
|
||||
if( !strcasecmp( ent->d_name, file ) ) {
|
||||
sprintf( filename, "%s%s%s", path,
|
||||
( ( path[ strlen( path ) - 1 ] == '/' ) ? "" : "/" ),
|
||||
ent->d_name );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
static int findDVDFile( dvd_reader_t *dvd, const char *file, char *filename )
|
||||
{
|
||||
char video_path[ PATH_MAX + 1 ];
|
||||
const char *nodirfile;
|
||||
int ret;
|
||||
|
||||
/* Strip off the directory for our search */
|
||||
if( !strncasecmp( "/VIDEO_TS/", file, 10 ) ) {
|
||||
nodirfile = &(file[ 10 ]);
|
||||
} else {
|
||||
nodirfile = file;
|
||||
}
|
||||
|
||||
ret = findDirFile( dvd->path_root, nodirfile, filename );
|
||||
if( ret < 0 ) {
|
||||
/* Try also with adding the path, just in case. */
|
||||
sprintf( video_path, "%s/VIDEO_TS/", dvd->path_root );
|
||||
ret = findDirFile( video_path, nodirfile, filename );
|
||||
if( ret < 0 ) {
|
||||
/* Try with the path, but in lower case. */
|
||||
sprintf( video_path, "%s/video_ts/", dvd->path_root );
|
||||
ret = findDirFile( video_path, nodirfile, filename );
|
||||
if( ret < 0 ) {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Open an unencrypted file from a DVD directory tree.
|
||||
*/
|
||||
static dvd_file_t *DVDOpenFilePath( dvd_reader_t *dvd, char *filename )
|
||||
{
|
||||
char full_path[ PATH_MAX + 1 ];
|
||||
dvd_file_t *dvd_file;
|
||||
struct stat fileinfo;
|
||||
int fd;
|
||||
|
||||
/* Get the full path of the file. */
|
||||
if( !findDVDFile( dvd, filename, full_path ) ) return 0;
|
||||
|
||||
fprintf( stderr, "libdvdread: opening %s as file\n", full_path );
|
||||
fd = open( full_path, O_RDONLY );
|
||||
if( fd < 0 ) return 0;
|
||||
|
||||
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
|
||||
if( !dvd_file ) return 0;
|
||||
dvd_file->dvd = dvd;
|
||||
dvd_file->lb_start = 0;
|
||||
dvd_file->seek_pos = 0;
|
||||
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
|
||||
memset( dvd_file->title_devs, -1, sizeof( dvd_file->title_devs ) );
|
||||
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) );
|
||||
dvd_file->filesize = 0;
|
||||
|
||||
if( stat( full_path, &fileinfo ) < 0 ) {
|
||||
fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
|
||||
free( dvd_file );
|
||||
return 0;
|
||||
}
|
||||
dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
|
||||
dvd_file->title_fds[ 0 ] = fd;
|
||||
dvd_file->filesize = dvd_file->title_sizes[ 0 ];
|
||||
|
||||
return dvd_file;
|
||||
}
|
||||
|
||||
static dvd_file_t *DVDOpenVOBUDF( dvd_reader_t *dvd,
|
||||
int title, int menu )
|
||||
{
|
||||
char filename[ MAX_UDF_FILE_NAME_LEN ];
|
||||
uint32_t start, len;
|
||||
dvd_file_t *dvd_file;
|
||||
|
||||
fprintf( stderr, "libdvdread: opening VOB as image\n" );
|
||||
if( title == 0 ) {
|
||||
sprintf( filename, "/VIDEO_TS/VIDEO_TS.VOB" );
|
||||
} else {
|
||||
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, menu ? 0 : 1 );
|
||||
}
|
||||
start = UDFFindFile( dvd, filename, &len );
|
||||
if( start == 0 ) return 0;
|
||||
|
||||
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
|
||||
if( !dvd_file ) return 0;
|
||||
dvd_file->dvd = dvd;
|
||||
dvd_file->lb_start = start;
|
||||
dvd_file->seek_pos = 0;
|
||||
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
|
||||
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) );
|
||||
dvd_file->filesize = len / DVD_VIDEO_LB_LEN;
|
||||
|
||||
/* Calculate the complete file size for every file in the VOBS */
|
||||
if( !menu ) {
|
||||
int cur;
|
||||
|
||||
for( cur = 2; cur < 10; cur++ ) {
|
||||
sprintf( filename, "/VIDEO_TS/VTS_%02d_%d.VOB", title, cur );
|
||||
if( !UDFFindFile( dvd, filename, &len ) ) break;
|
||||
dvd_file->filesize += len / DVD_VIDEO_LB_LEN;
|
||||
}
|
||||
}
|
||||
|
||||
if( dvdcss_seek( dvd_file->dvd->dev, (int)start, DVDCSS_SEEK_KEY ) < 0 ) {
|
||||
fprintf( stderr, "libdvdread: Error cracking CSS key for %s\n",
|
||||
filename );
|
||||
}
|
||||
|
||||
return dvd_file;
|
||||
}
|
||||
|
||||
static dvd_file_t *DVDOpenVOBPath( dvd_reader_t *dvd,
|
||||
int title, int menu )
|
||||
{
|
||||
char filename[ MAX_UDF_FILE_NAME_LEN ];
|
||||
char full_path[ PATH_MAX + 1 ];
|
||||
struct stat fileinfo;
|
||||
dvd_file_t *dvd_file;
|
||||
int i;
|
||||
|
||||
fprintf( stderr, "libdvdread: opening VOB as file\n" );
|
||||
dvd_file = (dvd_file_t *) malloc( sizeof( dvd_file_t ) );
|
||||
if( !dvd_file ) return 0;
|
||||
dvd_file->dvd = dvd;
|
||||
dvd_file->lb_start = 0;
|
||||
dvd_file->seek_pos = 0;
|
||||
memset( dvd_file->title_sizes, 0, sizeof( dvd_file->title_sizes ) );
|
||||
memset( dvd_file->title_devs, -1, sizeof( dvd_file->title_devs ) );
|
||||
memset( dvd_file->title_fds, -1, sizeof( dvd_file->title_fds ) );
|
||||
dvd_file->filesize = 0;
|
||||
|
||||
if( menu ) {
|
||||
int fd;
|
||||
|
||||
if( title == 0 ) {
|
||||
sprintf( filename, "VIDEO_TS.VOB" );
|
||||
} else {
|
||||
sprintf( filename, "VTS_%02i_0.VOB", title );
|
||||
}
|
||||
if( !findDVDFile( dvd, filename, full_path ) ) {
|
||||
free( dvd_file );
|
||||
return 0;
|
||||
}
|
||||
|
||||
fd = open( full_path, O_RDONLY );
|
||||
if( fd < 0 ) {
|
||||
free( dvd_file );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( stat( full_path, &fileinfo ) < 0 ) {
|
||||
fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
|
||||
free( dvd_file );
|
||||
return 0;
|
||||
}
|
||||
dvd_file->title_sizes[ 0 ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
|
||||
dvd_file->title_fds[ 0 ] = fd;
|
||||
dvd_file->title_devs[ 0 ] = dvdcss_open( full_path );
|
||||
dvdcss_title( dvd_file->title_devs[0], 0 );
|
||||
dvd_file->filesize = dvd_file->title_sizes[ 0 ];
|
||||
|
||||
} else {
|
||||
for( i = 0; i < 9; ++i ) {
|
||||
|
||||
sprintf( filename, "VTS_%02i_%i.VOB", title, i + 1 );
|
||||
if( !findDVDFile( dvd, filename, full_path ) ) {
|
||||
break;
|
||||
}
|
||||
|
||||
if( stat( full_path, &fileinfo ) < 0 ) {
|
||||
fprintf( stderr, "libdvdread: Can't stat() %s.\n", filename );
|
||||
break;
|
||||
}
|
||||
|
||||
dvd_file->title_sizes[ i ] = fileinfo.st_size / DVD_VIDEO_LB_LEN;
|
||||
dvd_file->title_fds[ i ] = open( full_path, O_RDONLY );
|
||||
dvd_file->title_devs[ i ] = dvdcss_open( full_path );
|
||||
dvdcss_title( dvd_file->title_devs[i], 0 );
|
||||
dvd_file->filesize += dvd_file->title_sizes[ i ];
|
||||
}
|
||||
if( !(dvd_file->title_sizes[ 0 ]) ) {
|
||||
free( dvd_file );
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
return dvd_file;
|
||||
}
|
||||
|
||||
dvd_file_t *DVDOpenFile( dvd_reader_t *dvd, int titlenum,
|
||||
dvd_read_domain_t domain )
|
||||
{
|
||||
char filename[ MAX_UDF_FILE_NAME_LEN ];
|
||||
|
||||
switch( domain ) {
|
||||
case DVD_READ_INFO_FILE:
|
||||
if( titlenum == 0 ) {
|
||||
sprintf( filename, "/VIDEO_TS/VIDEO_TS.IFO" );
|
||||
} else {
|
||||
sprintf( filename, "/VIDEO_TS/VTS_%02i_0.IFO", titlenum );
|
||||
}
|
||||
break;
|
||||
case DVD_READ_INFO_BACKUP_FILE:
|
||||
if( titlenum == 0 ) {
|
||||
sprintf( filename, "/VIDEO_TS/VIDEO_TS.BUP" );
|
||||
} else {
|
||||
sprintf( filename, "/VIDEO_TS/VTS_%02i_0.BUP", titlenum );
|
||||
}
|
||||
break;
|
||||
case DVD_READ_MENU_VOBS:
|
||||
if( dvd->isImageFile ) {
|
||||
return DVDOpenVOBUDF( dvd, titlenum, 1 );
|
||||
} else {
|
||||
return DVDOpenVOBPath( dvd, titlenum, 1 );
|
||||
}
|
||||
break;
|
||||
case DVD_READ_TITLE_VOBS:
|
||||
if( titlenum == 0 ) return 0;
|
||||
if( dvd->isImageFile ) {
|
||||
return DVDOpenVOBUDF( dvd, titlenum, 0 );
|
||||
} else {
|
||||
return DVDOpenVOBPath( dvd, titlenum, 0 );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf( stderr, "libdvdread: Invalid domain for file open.\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( dvd->isImageFile ) {
|
||||
return DVDOpenFileUDF( dvd, filename );
|
||||
} else {
|
||||
return DVDOpenFilePath( dvd, filename );
|
||||
}
|
||||
}
|
||||
|
||||
void DVDCloseFile( dvd_file_t *dvd_file )
|
||||
{
|
||||
int i;
|
||||
|
||||
if( dvd_file ) {
|
||||
if( !dvd_file->dvd->isImageFile ) {
|
||||
for( i = 0; i < 9; ++i ) {
|
||||
if( dvd_file->title_fds[ i ] >= 0 )
|
||||
{
|
||||
close( dvd_file->title_fds[ i ] );
|
||||
dvdcss_close( dvd_file->title_devs[i] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
free( dvd_file );
|
||||
dvd_file = 0;
|
||||
}
|
||||
}
|
||||
|
||||
int64_t DVDReadLBUDF( dvd_reader_t *device, uint32_t lb_number,
|
||||
size_t block_count, unsigned char *data,
|
||||
int encrypted )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if( !device->dev ) {
|
||||
fprintf( stderr, "libdvdread: Fatal error in block read.\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = dvdcss_seek( device->dev, (int) lb_number, DVDCSS_NOFLAGS );
|
||||
if( ret != (int) lb_number ) {
|
||||
fprintf( stderr, "libdvdread: Can't seek to block %u\n",
|
||||
lb_number );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int64_t) ( dvdcss_read( device->dev, (char *) data,
|
||||
(int) block_count, encrypted )
|
||||
* (uint64_t) DVD_VIDEO_LB_LEN );
|
||||
}
|
||||
|
||||
static int64_t DVDReadBlocksUDF( dvd_file_t *dvd_file, uint32_t offset,
|
||||
size_t block_count, unsigned char *data )
|
||||
{
|
||||
return DVDReadLBUDF( dvd_file->dvd, dvd_file->lb_start + offset,
|
||||
block_count, data, DVDCSS_READ_DECRYPT );
|
||||
}
|
||||
|
||||
static int64_t DVDReadBlocksPath( dvd_file_t *dvd_file, size_t offset,
|
||||
size_t block_count, unsigned char *data )
|
||||
{
|
||||
int i;
|
||||
ssize_t ret, ret2;
|
||||
off64_t off;
|
||||
|
||||
ret = 0;
|
||||
ret2 = 0;
|
||||
for( i = 0; i < 9; ++i ) {
|
||||
if( !dvd_file->title_sizes[ i ] ) return 0;
|
||||
|
||||
if( offset < dvd_file->title_sizes[ i ] ) {
|
||||
if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] ) {
|
||||
off = lseek64( dvd_file->title_fds[ i ],
|
||||
offset * (int64_t) DVD_VIDEO_LB_LEN, SEEK_SET );
|
||||
if( off != ( offset * (int64_t) DVD_VIDEO_LB_LEN ) ) {
|
||||
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
|
||||
offset );
|
||||
return 0;
|
||||
}
|
||||
ret = read( dvd_file->title_fds[ i ], data,
|
||||
block_count * DVD_VIDEO_LB_LEN );
|
||||
break;
|
||||
} else {
|
||||
size_t part1_size
|
||||
= ( dvd_file->title_sizes[ i ] - offset ) * DVD_VIDEO_LB_LEN;
|
||||
/* FIXME: Really needs to be a while loop.
|
||||
(This is only true if you try and read >1GB at a time) */
|
||||
|
||||
/* Read part 1 */
|
||||
off = lseek64( dvd_file->title_fds[ i ],
|
||||
offset * (int64_t) DVD_VIDEO_LB_LEN, SEEK_SET );
|
||||
if( off != ( offset * (int64_t) DVD_VIDEO_LB_LEN ) ) {
|
||||
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
|
||||
offset );
|
||||
return 0;
|
||||
}
|
||||
ret = read( dvd_file->title_fds[ i ], data, part1_size );
|
||||
if( ret < 0 ) return ret;
|
||||
/* FIXME: This is wrong if i is the last file in the set.
|
||||
also error from this read will not show in ret. */
|
||||
|
||||
/* Read part 2 */
|
||||
lseek64( dvd_file->title_fds[ i + 1 ], (off64_t)0, SEEK_SET );
|
||||
ret2 = read( dvd_file->title_fds[ i + 1 ], data + part1_size,
|
||||
block_count * DVD_VIDEO_LB_LEN - part1_size );
|
||||
if( ret2 < 0 ) return ret2;
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
offset -= dvd_file->title_sizes[ i ];
|
||||
}
|
||||
}
|
||||
|
||||
return ( (int64_t) ret + (int64_t) ret2 );
|
||||
}
|
||||
|
||||
/* These are broken for some cases reading more than 2Gb at a time. */
|
||||
ssize_t DVDReadBlocks( dvd_file_t *dvd_file, int offset,
|
||||
size_t block_count, unsigned char *data )
|
||||
{
|
||||
int64_t ret;
|
||||
|
||||
if( dvd_file->dvd->isImageFile ) {
|
||||
ret = DVDReadBlocksUDF( dvd_file, (uint32_t)offset,
|
||||
block_count, data );
|
||||
} else {
|
||||
ret = DVDReadBlocksPath( dvd_file, (size_t) offset,
|
||||
block_count, data );
|
||||
}
|
||||
if( ret <= 0 ) {
|
||||
return (ssize_t) ret;
|
||||
}
|
||||
{
|
||||
ssize_t sret = (ssize_t) (ret / (int64_t)DVD_VIDEO_LB_LEN );
|
||||
if( sret == 0 ) {
|
||||
fprintf(stderr, "libdvdread: DVDReadBlocks got %d bytes\n", (int)ret );
|
||||
}
|
||||
return sret;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t DVDFileSeek( dvd_file_t *dvd_file, int32_t offset )
|
||||
{
|
||||
if( dvd_file->dvd->isImageFile ) {
|
||||
dvd_file->seek_pos = (uint32_t) offset;
|
||||
return offset;
|
||||
} else {
|
||||
return (int32_t) ( lseek( dvd_file->title_fds[ 0 ],
|
||||
(off_t) offset, SEEK_SET ) );
|
||||
}
|
||||
}
|
||||
|
||||
static ssize_t DVDReadBytesUDF( dvd_file_t *dvd_file, void *data,
|
||||
size_t byte_size )
|
||||
{
|
||||
unsigned char *secbuf;
|
||||
unsigned int numsec, seek_sector, seek_byte;
|
||||
int64_t len;
|
||||
|
||||
seek_sector = dvd_file->seek_pos / DVD_VIDEO_LB_LEN;
|
||||
seek_byte = dvd_file->seek_pos % DVD_VIDEO_LB_LEN;
|
||||
|
||||
numsec = ( ( seek_byte + byte_size ) / DVD_VIDEO_LB_LEN ) + 1;
|
||||
secbuf = (unsigned char *) malloc( numsec * DVD_VIDEO_LB_LEN );
|
||||
if( !secbuf ) {
|
||||
fprintf( stderr, "libdvdread: Can't allocate memory "
|
||||
"for file read!\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
len = DVDReadLBUDF( dvd_file->dvd, dvd_file->lb_start + seek_sector,
|
||||
numsec, secbuf, DVDCSS_NOFLAGS );
|
||||
if( len != numsec * (int64_t) DVD_VIDEO_LB_LEN ) {
|
||||
free( secbuf );
|
||||
return 0;
|
||||
}
|
||||
|
||||
dvd_file->seek_pos += byte_size;
|
||||
|
||||
memcpy( data, &(secbuf[ seek_byte ]), byte_size );
|
||||
free( secbuf );
|
||||
|
||||
return byte_size;
|
||||
}
|
||||
|
||||
static ssize_t DVDReadBytesPath( dvd_file_t *dvd_file, void *data,
|
||||
size_t byte_size )
|
||||
{
|
||||
return read( dvd_file->title_fds[ 0 ], data, byte_size );
|
||||
}
|
||||
|
||||
ssize_t DVDReadBytes( dvd_file_t *dvd_file, void *data, size_t byte_size )
|
||||
{
|
||||
if( dvd_file->dvd->isImageFile ) {
|
||||
return DVDReadBytesUDF( dvd_file, data, byte_size );
|
||||
} else {
|
||||
return DVDReadBytesPath( dvd_file, data, byte_size );
|
||||
}
|
||||
}
|
||||
|
||||
ssize_t DVDFileSize( dvd_file_t *dvd_file )
|
||||
{
|
||||
return dvd_file->filesize;
|
||||
}
|
||||
|
||||
int64_t DVDReadVLBUDF( dvd_reader_t *device, uint32_t lb_number,
|
||||
size_t block_count, struct iovec * vector,
|
||||
int encrypted )
|
||||
{
|
||||
int ret;
|
||||
|
||||
if( !device->dev ) {
|
||||
fprintf( stderr, "libdvdread: Fatal error in block read.\n" );
|
||||
return 0;
|
||||
}
|
||||
|
||||
ret = dvdcss_seek( device->dev, (int) lb_number, 0 );
|
||||
if( ret != (int) lb_number ) {
|
||||
fprintf( stderr, "libdvdread: Can't seek to block %u\n",
|
||||
lb_number );
|
||||
return 0;
|
||||
}
|
||||
|
||||
return (int64_t) ( dvdcss_readv( device->dev, vector,
|
||||
(int)block_count, encrypted )
|
||||
* (uint64_t) DVD_VIDEO_LB_LEN );
|
||||
}
|
||||
|
||||
static int64_t DVDReadVBlocksUDF( dvd_file_t *dvd_file, uint32_t offset,
|
||||
size_t block_count, struct iovec *vector )
|
||||
{
|
||||
return DVDReadVLBUDF( dvd_file->dvd, dvd_file->lb_start + offset,
|
||||
block_count, vector, DVDCSS_READ_DECRYPT );
|
||||
}
|
||||
|
||||
static int64_t DVDReadVBlocksPath( dvd_file_t *dvd_file, size_t offset,
|
||||
size_t block_count, struct iovec *vector )
|
||||
{
|
||||
int i;
|
||||
int ret, ret2;
|
||||
int off;
|
||||
|
||||
ret = 0;
|
||||
ret2 = 0;
|
||||
for( i = 0 ; i < 9 ; ++i )
|
||||
{
|
||||
if( !dvd_file->title_sizes[ i ] )
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
|
||||
if( offset < dvd_file->title_sizes[ i ] )
|
||||
{
|
||||
if( ( offset + block_count ) <= dvd_file->title_sizes[ i ] )
|
||||
{
|
||||
off = dvdcss_seek( dvd_file->title_devs[ i ],
|
||||
(int)offset, 0 );
|
||||
if( off != (int)offset )
|
||||
{
|
||||
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
|
||||
offset );
|
||||
return 0;
|
||||
}
|
||||
ret = dvdcss_readv( dvd_file->title_devs[ i ], vector,
|
||||
(int)block_count, DVDCSS_READ_DECRYPT );
|
||||
break;
|
||||
}
|
||||
else
|
||||
{
|
||||
int part1_size = dvd_file->title_sizes[ i ] - offset;
|
||||
/* FIXME: Really needs to be a while loop.
|
||||
(This is only true if you try and read >1GB at a time) */
|
||||
|
||||
/* Read part 1 */
|
||||
off = dvdcss_seek( dvd_file->title_devs[ i ], offset, 0 );
|
||||
if( off != offset )
|
||||
{
|
||||
fprintf( stderr, "libdvdread: Can't seek to block %d\n",
|
||||
offset );
|
||||
return 0;
|
||||
}
|
||||
ret = dvdcss_readv( dvd_file->title_devs[ i ], vector,
|
||||
part1_size, DVDCSS_READ_DECRYPT );
|
||||
|
||||
if( ret < 0 ) return ret;
|
||||
/* FIXME: This is wrong if i is the last file in the set.
|
||||
also error from this read will not show in ret. */
|
||||
|
||||
/* Read part 2 */
|
||||
dvdcss_seek( dvd_file->title_devs[ i + 1 ], 0, 0 );
|
||||
ret2 = dvdcss_readv( dvd_file->title_devs[ i + 1 ],
|
||||
vector + part1_size, (int)(block_count - part1_size),
|
||||
DVDCSS_READ_DECRYPT );
|
||||
if( ret2 < 0 ) return ret2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
offset -= dvd_file->title_sizes[ i ];
|
||||
}
|
||||
}
|
||||
|
||||
return ( ret + ret2 ) * (int64_t) DVD_VIDEO_LB_LEN;
|
||||
}
|
||||
|
||||
|
||||
ssize_t DVDReadVBlocks( dvd_file_t *dvd_file, int offset,
|
||||
size_t block_count, struct iovec * vector )
|
||||
{
|
||||
int64_t ret;
|
||||
|
||||
if( dvd_file->dvd->isImageFile )
|
||||
{
|
||||
ret = DVDReadVBlocksUDF( dvd_file, (uint32_t)offset,
|
||||
block_count, vector );
|
||||
}
|
||||
else
|
||||
{
|
||||
ret = DVDReadVBlocksPath( dvd_file, (size_t) offset,
|
||||
block_count, vector );
|
||||
}
|
||||
if( ret <= 0 )
|
||||
{
|
||||
return (ssize_t) ret;
|
||||
}
|
||||
|
||||
{
|
||||
ssize_t sret = (ssize_t) (ret / (int64_t)DVD_VIDEO_LB_LEN );
|
||||
if( sret == 0 )
|
||||
{
|
||||
fprintf(stderr, "libdvdread: DVDReadVBlocks got %d bytes\n", (int)ret );
|
||||
}
|
||||
return sret;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -1,25 +0,0 @@
|
||||
/*****************************************************************************
|
||||
* dvdread.h: DVD reading library, exported functions.
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1998-2001 VideoLAN
|
||||
* $Id: dvdread.h,v 1.1 2001/11/25 05:04:38 stef Exp $
|
||||
*
|
||||
* Authors: Stéphane Borel <stef@via.ecp.fr>
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation; either version 2 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program; if not, write to the Free Software
|
||||
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
|
||||
*****************************************************************************/
|
||||
|
||||
ssize_t DVDReadVBlocks( dvd_file_t *dvd_file, int offset,
|
||||
size_t block_count, struct iovec * vector );
|
@ -1,4 +1,4 @@
|
||||
/* include/defs.h.in. Generated automatically from configure.in by autoheader. */
|
||||
/* include/defs.h.in. Generated automatically from configure.in by autoheader 2.13. */
|
||||
|
||||
/* Define if using alloca.c. */
|
||||
#undef C_ALLOCA
|
||||
|
@ -2,7 +2,7 @@
|
||||
* dummy_dvdcss.h: Dummy libdvdcss header.
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
* $Id: dummy_dvdcss.h,v 1.6 2002/01/07 02:12:29 sam Exp $
|
||||
* $Id: dummy_dvdcss.h,v 1.7 2002/01/23 03:15:31 stef Exp $
|
||||
*
|
||||
* Authors: Samuel Hocevar <sam@zoy.org>
|
||||
*
|
||||
@ -51,14 +51,6 @@ char * dummy_dvdcss_error ( dvdcss_handle );
|
||||
* Pointers which will be filled either with dummy_dvdcss functions or
|
||||
* with the dlopen()ed ones.
|
||||
*****************************************************************************/
|
||||
dvdcss_handle (* ____dvdcss_open ) ( char * );
|
||||
int (* ____dvdcss_close ) ( dvdcss_handle );
|
||||
int (* ____dvdcss_title ) ( dvdcss_handle, int );
|
||||
int (* ____dvdcss_seek ) ( dvdcss_handle, int, int );
|
||||
int (* ____dvdcss_read ) ( dvdcss_handle, void *, int, int );
|
||||
int (* ____dvdcss_readv ) ( dvdcss_handle, void *, int, int );
|
||||
char * (* ____dvdcss_error ) ( dvdcss_handle );
|
||||
|
||||
#define ____dvdcss_open dvdcss_open
|
||||
#define ____dvdcss_close dvdcss_close
|
||||
#define ____dvdcss_title dvdcss_title
|
||||
@ -67,3 +59,12 @@ char * (* ____dvdcss_error ) ( dvdcss_handle );
|
||||
#define ____dvdcss_readv dvdcss_readv
|
||||
#define ____dvdcss_error dvdcss_error
|
||||
|
||||
dvdcss_handle (* ____dvdcss_open ) ( char * );
|
||||
int (* ____dvdcss_close ) ( dvdcss_handle );
|
||||
int (* ____dvdcss_title ) ( dvdcss_handle, int );
|
||||
int (* ____dvdcss_seek ) ( dvdcss_handle, int, int );
|
||||
int (* ____dvdcss_read ) ( dvdcss_handle, void *, int, int );
|
||||
int (* ____dvdcss_readv ) ( dvdcss_handle, void *, int, int );
|
||||
char * (* ____dvdcss_error ) ( dvdcss_handle );
|
||||
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
* dvdread.c : DvdRead input module for vlc
|
||||
*****************************************************************************
|
||||
* Copyright (C) 2001 VideoLAN
|
||||
* $Id: dvdread.c,v 1.7 2002/01/08 23:34:06 stef Exp $
|
||||
* $Id: dvdread.c,v 1.8 2002/01/23 03:15:31 stef Exp $
|
||||
*
|
||||
* Authors: Samuel Hocevar <sam@zoy.org>
|
||||
*
|
||||
@ -29,25 +29,11 @@
|
||||
|
||||
#include <videolan/vlc.h>
|
||||
|
||||
#ifdef GOD_DAMN_DMCA
|
||||
# include <dlfcn.h>
|
||||
# include "dummy_dvdcss.h"
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* Capabilities defined in the other files.
|
||||
*****************************************************************************/
|
||||
void _M( input_getfunctions )( function_list_t * p_function_list );
|
||||
|
||||
/*****************************************************************************
|
||||
* Local prototypes.
|
||||
*****************************************************************************/
|
||||
#ifdef GOD_DAMN_DMCA
|
||||
static void *p_libdvdcss;
|
||||
static void ProbeLibDVDCSS ( void );
|
||||
static void UnprobeLibDVDCSS( void );
|
||||
#endif
|
||||
|
||||
/*****************************************************************************
|
||||
* Build configuration tree.
|
||||
*****************************************************************************/
|
||||
@ -55,130 +41,15 @@ MODULE_CONFIG_START
|
||||
MODULE_CONFIG_STOP
|
||||
|
||||
MODULE_INIT_START
|
||||
#ifdef GOD_DAMN_DMCA
|
||||
SET_DESCRIPTION( "DVDRead input module, uses libdvdcss if present" )
|
||||
ADD_CAPABILITY( INPUT, 70 )
|
||||
#else
|
||||
SET_DESCRIPTION( "DVDRead input module, linked with libdvdcss" )
|
||||
SET_DESCRIPTION( "DVDRead input module" )
|
||||
ADD_CAPABILITY( INPUT, 110 )
|
||||
#endif
|
||||
ADD_SHORTCUT( "dvdread" )
|
||||
|
||||
MODULE_INIT_STOP
|
||||
|
||||
MODULE_ACTIVATE_START
|
||||
_M( input_getfunctions )( &p_module->p_functions->input );
|
||||
#ifdef GOD_DAMN_DMCA
|
||||
ProbeLibDVDCSS();
|
||||
#endif
|
||||
MODULE_ACTIVATE_STOP
|
||||
|
||||
MODULE_DEACTIVATE_START
|
||||
#ifdef GOD_DAMN_DMCA
|
||||
UnprobeLibDVDCSS();
|
||||
#endif
|
||||
MODULE_DEACTIVATE_STOP
|
||||
|
||||
|
||||
/* Following functions are local */
|
||||
|
||||
#ifdef GOD_DAMN_DMCA
|
||||
/*****************************************************************************
|
||||
* ProbeLibDVDCSS: look for a libdvdcss object.
|
||||
*****************************************************************************
|
||||
* This functions looks for libdvdcss, using dlopen(), and fills function
|
||||
* pointers with what it finds. On failure, uses the dummy libdvdcss
|
||||
* replacement provided by vlc.
|
||||
*****************************************************************************/
|
||||
static void ProbeLibDVDCSS( void )
|
||||
{
|
||||
char *pp_filelist[4] = { "libdvdcss.so.0",
|
||||
"./libdvdcss.so.0",
|
||||
"./lib/libdvdcss.so.0",
|
||||
NULL };
|
||||
char **pp_file = pp_filelist;
|
||||
|
||||
/* Try to open the dynamic object */
|
||||
do
|
||||
{
|
||||
p_libdvdcss = dlopen( *pp_file, RTLD_LAZY );
|
||||
if( p_libdvdcss != NULL )
|
||||
{
|
||||
intf_WarnMsg( 2, "module: builtin module `dvd' found libdvdcss "
|
||||
"in `%s'", *pp_file );
|
||||
break;
|
||||
}
|
||||
pp_file++;
|
||||
|
||||
} while( *pp_file != NULL );
|
||||
|
||||
/* If libdvdcss.so was found, check that it's valid */
|
||||
if( p_libdvdcss == NULL )
|
||||
{
|
||||
intf_ErrMsg( "dvd warning: libdvdcss.so.0 not present" );
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Check for libdvdcss 0.0.1 */
|
||||
if( dlsym( p_libdvdcss, "dvdcss_crack" ) != NULL )
|
||||
{
|
||||
intf_ErrMsg( "dvd warning: libdvdcss.so.0 has deprecated symbol "
|
||||
"dvdcss_crack(), please upgrade" );
|
||||
dlclose( p_libdvdcss );
|
||||
p_libdvdcss = NULL;
|
||||
}
|
||||
else
|
||||
{
|
||||
dvdcss_open = dlsym( p_libdvdcss, "dvdcss_open" );
|
||||
dvdcss_close = dlsym( p_libdvdcss, "dvdcss_close" );
|
||||
dvdcss_title = dlsym( p_libdvdcss, "dvdcss_title" );
|
||||
dvdcss_seek = dlsym( p_libdvdcss, "dvdcss_seek" );
|
||||
dvdcss_read = dlsym( p_libdvdcss, "dvdcss_read" );
|
||||
dvdcss_readv = dlsym( p_libdvdcss, "dvdcss_readv" );
|
||||
dvdcss_error = dlsym( p_libdvdcss, "dvdcss_error" );
|
||||
|
||||
if( dvdcss_open == NULL || dvdcss_close == NULL
|
||||
|| dvdcss_title == NULL || dvdcss_seek == NULL
|
||||
|| dvdcss_read == NULL || dvdcss_readv == NULL
|
||||
|| dvdcss_error == NULL )
|
||||
{
|
||||
intf_ErrMsg( "dvd warning: missing symbols in libdvdcss.so.0, "
|
||||
"please upgrade libdvdcss or vlc" );
|
||||
dlclose( p_libdvdcss );
|
||||
p_libdvdcss = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If libdvdcss was not found or was not valid, use the dummy
|
||||
* replacement functions. */
|
||||
if( p_libdvdcss == NULL )
|
||||
{
|
||||
intf_ErrMsg( "dvd warning: no valid libdvdcss found, "
|
||||
"I will only play unencrypted DVDs" );
|
||||
intf_ErrMsg( "dvd warning: get libdvdcss at "
|
||||
"http://www.videolan.org/libdvdcss/" );
|
||||
|
||||
dvdcss_open = dummy_dvdcss_open;
|
||||
dvdcss_close = dummy_dvdcss_close;
|
||||
dvdcss_title = dummy_dvdcss_title;
|
||||
dvdcss_seek = dummy_dvdcss_seek;
|
||||
dvdcss_read = dummy_dvdcss_read;
|
||||
dvdcss_readv = dummy_dvdcss_readv;
|
||||
dvdcss_error = dummy_dvdcss_error;
|
||||
}
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
* UnprobeLibDVDCSS: free resources allocated by ProbeLibDVDCSS, if any.
|
||||
*****************************************************************************/
|
||||
static void UnprobeLibDVDCSS( void )
|
||||
{
|
||||
if( p_libdvdcss != NULL )
|
||||
{
|
||||
dlclose( p_libdvdcss );
|
||||
p_libdvdcss = NULL;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -2,7 +2,7 @@
|
||||
* input_dvdread.h: thread structure of the DVD plugin
|
||||
*****************************************************************************
|
||||
* Copyright (C) 1999-2001 VideoLAN
|
||||
* $Id: input_dvdread.h,v 1.3 2001/12/29 22:22:01 massiot Exp $
|
||||
* $Id: input_dvdread.h,v 1.4 2002/01/23 03:15:31 stef Exp $
|
||||
*
|
||||
* Author: Stéphane Borel <stef@via.ecp.fr>
|
||||
*
|
||||
@ -32,7 +32,6 @@
|
||||
#include "dvd_udf.h"
|
||||
#include "nav_read.h"
|
||||
#include "nav_print.h"
|
||||
#include "videolan/dvdread.h"
|
||||
|
||||
/* Logical block size for DVD-VIDEO */
|
||||
#define LB2OFF(x) ((off_t)(x) * (off_t)(DVD_VIDEO_LB_LEN))
|
||||
|
Loading…
Reference in New Issue
Block a user