summaryrefslogtreecommitdiffstats
path: root/libmpdvdkit2/libdvdcss.c
diff options
context:
space:
mode:
authorarpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2>2003-02-08 00:22:39 +0000
committerarpi <arpi@b3059339-0415-0410-9bf9-f77b7e298cf2>2003-02-08 00:22:39 +0000
commitb606cb19527d294cfd05011de5dfd47b6c023296 (patch)
tree3ff67c8a11c35dceae1e87617329133dbd566dc8 /libmpdvdkit2/libdvdcss.c
parent4e8a50437110dc3d70e406c8d3dbf2a522ff5594 (diff)
downloadmpv-b606cb19527d294cfd05011de5dfd47b6c023296.tar.bz2
mpv-b606cb19527d294cfd05011de5dfd47b6c023296.tar.xz
sync with libdvdcss 1.2.5 (including u8->uint8_t and whitespace cosmetics...)
patch by Andreas Hess <jaska@gmx.net> git-svn-id: svn://svn.mplayerhq.hu/mplayer/trunk@9334 b3059339-0415-0410-9bf9-f77b7e298cf2
Diffstat (limited to 'libmpdvdkit2/libdvdcss.c')
-rw-r--r--libmpdvdkit2/libdvdcss.c258
1 files changed, 181 insertions, 77 deletions
diff --git a/libmpdvdkit2/libdvdcss.c b/libmpdvdkit2/libdvdcss.c
index b287da3f63..b30ec47414 100644
--- a/libmpdvdkit2/libdvdcss.c
+++ b/libmpdvdkit2/libdvdcss.c
@@ -11,7 +11,7 @@
* 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
@@ -22,7 +22,7 @@
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111, USA.
*/
-/**
+/**
* \mainpage libdvdcss developer documentation
*
* \section intro Introduction
@@ -77,8 +77,17 @@
* decrypt a DVD stored on a hard disc, or a DVD with the wrong region
* on an RPC2 drive.
*
- * \li \b DVDCSS_RAW_DEVICE: specify the raw device to use.
- *
+ * \li \b DVDCSS_RAW_DEVICE: specify the raw device to use. Exact usage will
+ * depend on your operating system, the Linux utility to set up raw devices
+ * is \c raw(8) for instance. Please note that on most operating systems,
+ * using a raw device requires highly aligned buffers: Linux requires a
+ * 2048 bytes alignment (which is the size of a DVD sector).
+ *
+ * \li \b DVDCSS_CACHE: specify a directory in which to store title key
+ * values. This will speed up descrambling of DVDs which are in the
+ * cache. The DVDCSS_CACHE directory is created if it does not exist,
+ * and a subdirectory is created named after the DVD's title or
+ * manufacturing date.
*/
/*
@@ -92,10 +101,9 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
-
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif
+#include <errno.h>
+#include <unistd.h>
+#include <limits.h>
#include "dvdcss.h"
@@ -117,8 +125,6 @@
*/
char * dvdcss_interface_2 = VERSION;
-char * dvdcss_cache_dir = NULL;
-
/**
* \brief Open a DVD device or directory and return a dvdcss instance.
*
@@ -139,6 +145,7 @@ extern dvdcss_t dvdcss_open ( char *psz_target )
char *psz_method = getenv( "DVDCSS_METHOD" );
char *psz_verbose = getenv( "DVDCSS_VERBOSE" );
+ char *psz_cache = getenv( "DVDCSS_CACHE" );
#ifndef WIN32
char *psz_raw_device = getenv( "DVDCSS_RAW_DEVICE" );
#endif
@@ -164,9 +171,9 @@ extern dvdcss_t dvdcss_open ( char *psz_target )
dvdcss->psz_device = (char *)strdup( psz_target );
dvdcss->psz_error = "no error";
dvdcss->i_method = DVDCSS_METHOD_KEY;
+ dvdcss->psz_cachefile[0] = '\0';
dvdcss->b_debug = 0;
dvdcss->b_errors = 0;
- dvdcss->psz_cache = NULL;
/*
* Find verbosity from DVDCSS_VERBOSE environment variable
@@ -211,7 +218,23 @@ extern dvdcss_t dvdcss_open ( char *psz_target )
}
}
- if(!dvdcss_cache_dir) dvdcss_cache_dir = getenv( "DVDCSS_CACHE" );
+ /*
+ * Find cache dir from the DVDCSS_CACHE environment variable
+ */
+ if( psz_cache != NULL )
+ {
+ if( psz_cache[0] == '\0' )
+ {
+ psz_cache = NULL;
+ }
+ /* Check that we can add the ID directory and the block filename */
+ else if( strlen( psz_cache ) + 1 + 32 + 1 + 10 + 1 > PATH_MAX )
+ {
+ _dvdcss_error( dvdcss, "cache directory name is too long" );
+ psz_cache = NULL;
+ }
+ }
+ else psz_cache = get_path( "DVDKeys" );
/*
* Open device
@@ -223,26 +246,26 @@ extern dvdcss_t dvdcss_open ( char *psz_target )
free( dvdcss );
return NULL;
}
-
+
dvdcss->b_scrambled = 1; /* Assume the worst */
dvdcss->b_ioctls = _dvdcss_use_ioctls( dvdcss );
if( dvdcss->b_ioctls )
{
i_ret = _dvdcss_test( dvdcss );
- if( i_ret < 0 )
- {
- /* Disable the CSS ioctls and hope that it works? */
+ if( i_ret < 0 )
+ {
+ /* Disable the CSS ioctls and hope that it works? */
_dvdcss_debug( dvdcss,
"could not check whether the disc was scrambled" );
- dvdcss->b_ioctls = 0;
- }
- else
- {
+ dvdcss->b_ioctls = 0;
+ }
+ else
+ {
_dvdcss_debug( dvdcss, i_ret ? "disc is scrambled"
: "disc is unscrambled" );
- dvdcss->b_scrambled = i_ret;
- }
+ dvdcss->b_scrambled = i_ret;
+ }
}
/* If disc is CSS protected and the ioctls work, authenticate the drive */
@@ -266,46 +289,127 @@ extern dvdcss_t dvdcss_open ( char *psz_target )
}
#endif
- /* if the CACHE is enabled, extract some unique disc ID */
- if(dvdcss_cache_dir){
- char* disc_id=NULL;
- /*char title_name[64];*/
- char sector[DVDCSS_BLOCK_SIZE];
- // 32768+40 -> disc title (32 uppercase chars)
- // 32768+813 -> disc manufacturing date + serial no (16 digit number)
- int ret=dvdcss->pf_seek( dvdcss, 32768/DVDCSS_BLOCK_SIZE);
- //printf("disc_id seek: %d -> %d, i_fd=%d i_read_fd=%d\n",32768/DVDCSS_BLOCK_SIZE,ret,dvdcss->i_fd,dvdcss->i_read_fd);
- if(dvdcss->pf_read( dvdcss, sector, 1) == 1){
- // check disc title first:
- char* title_name=&sector[40];
- int i=0;
- while(i<32 && title_name[i]>='0' && title_name[i]<='z') i++;
- title_name[i]=0;
- if(i>5){
- disc_id=strdup(title_name);
- } else {
- // use disc date+serial:
- title_name=&sector[813];
- title_name[16]=0;
- for ( i=0;i<16;i++ )
- if ( ( title_name[i] < '0' )||( title_name[i] > '9' ) ){
- disc_id=malloc(16+4);
- snprintf( disc_id,17,"%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X",title_name[0],title_name[1],title_name[2],title_name[3],title_name[4],title_name[5],title_name[6],title_name[7] );
- break;
- }
- if(!disc_id) disc_id=strdup(title_name);
- }
- if(disc_id){
- // yeah, we have a disc name/id, let's set up cache path:
- /*char* dir;*/
- dvdcss->psz_cache = malloc(strlen(dvdcss_cache_dir)+strlen(disc_id)+4);
- sprintf(dvdcss->psz_cache,"%s/%s",dvdcss_cache_dir,disc_id);
- mkdir( dvdcss->psz_cache,493 );
- free(disc_id);
- fprintf(stderr,"Using CSS Key-cache dir: %s\n",dvdcss->psz_cache);
- }
- }
+ /* If the cache is enabled, extract a unique disc ID */
+ if( psz_cache )
+ {
+ uint8_t p_sector[DVDCSS_BLOCK_SIZE];
+ unsigned char psz_debug[PATH_MAX+30];
+ unsigned char * psz_data;
+ int i;
+
+ /* We read sector 0. If it starts with 0x000001ba (BE), we are
+ * reading a VOB file, and we should not cache anything. */
+
+ i_ret = dvdcss->pf_seek( dvdcss, 0 );
+ if( i_ret != 0 )
+ {
+ goto nocache;
+ }
+
+ i_ret = dvdcss->pf_read( dvdcss, p_sector, 1 );
+ if( i_ret != 1 )
+ {
+ goto nocache;
+ }
+
+ if( p_sector[0] == 0x00 && p_sector[1] == 0x00
+ && p_sector[2] == 0x01 && p_sector[3] == 0xba )
+ {
+ goto nocache;
+ }
+
+ /* The data we are looking for is at sector 16 (32768 bytes):
+ * - offset 40: disc title (32 uppercase chars)
+ * - offset 813: manufacturing date + serial no (16 digits) */
+
+ i_ret = dvdcss->pf_seek( dvdcss, 16 );
+ if( i_ret != 16 )
+ {
+ goto nocache;
+ }
+
+ i_ret = dvdcss->pf_read( dvdcss, p_sector, 1 );
+ if( i_ret != 1 )
+ {
+ goto nocache;
+ }
+
+ /* Get the disc title */
+ psz_data = p_sector + 40;
+ psz_data[32] = '\0';
+
+ for( i = 0 ; i < 32 ; i++ )
+ {
+ if( psz_data[i] <= ' ' )
+ {
+ psz_data[i] = '\0';
+ break;
+ }
+ else if( psz_data[i] == '/' || psz_data[i] == '\\' )
+ {
+ psz_data[i] = '-';
+ }
+ }
+
+ /* If it's not long enough, try the date + serial */
+ if( strlen( psz_data ) < 6 )
+ {
+ psz_data = p_sector + 813;
+ psz_data[16] = '\0';
+
+ /* Check that all characters are digits, otherwise convert. */
+ for( i = 0 ; i < 16 ; i++ )
+ {
+ if( psz_data[i] < '0' || psz_data[i] > '9' )
+ {
+ sprintf( psz_data,
+ "%.2X%.2X%.2X%.2X%.2X%.2X%.2X%.2X",
+ psz_data[0], psz_data[1], psz_data[2],
+ psz_data[3], psz_data[4], psz_data[5],
+ psz_data[6], psz_data[7] );
+ break;
+ }
+ }
+ }
+
+ /* We have a disc name or ID, we can create the cache dir */
+ i = sprintf( dvdcss->psz_cachefile, "%s", psz_cache );
+#if !defined( WIN32 ) || defined( SYS_CYGWIN )
+ i_ret = mkdir( dvdcss->psz_cachefile, 0755 );
+#else
+ i_ret = mkdir( dvdcss->psz_cachefile );
+#endif
+ if( i_ret < 0 && errno != EEXIST )
+ {
+ _dvdcss_error( dvdcss, "failed creating cache directory" );
+ dvdcss->psz_cachefile[0] = '\0';
+ goto nocache;
+ }
+
+ i += sprintf( dvdcss->psz_cachefile + i, "/%s/", psz_data );
+#if !defined( WIN32 ) || defined( SYS_CYGWIN )
+ i_ret = mkdir( dvdcss->psz_cachefile, 0755 );
+#else
+ i_ret = mkdir( dvdcss->psz_cachefile );
+#endif
+ if( i_ret < 0 && errno != EEXIST )
+ {
+ _dvdcss_error( dvdcss, "failed creating cache subdirectory" );
+ dvdcss->psz_cachefile[0] = '\0';
+ goto nocache;
+ }
+
+ /* Pointer to the filename we will use. */
+ dvdcss->psz_block = dvdcss->psz_cachefile + i;
+
+ sprintf( psz_debug, "using CSS key cache dir: %s",
+ dvdcss->psz_cachefile );
+ _dvdcss_debug( dvdcss, psz_debug );
}
+ nocache:
+
+ /* Seek at the beginning, just for safety. */
+ dvdcss->pf_seek( dvdcss, 0 );
return dvdcss;
}
@@ -354,11 +458,11 @@ extern int dvdcss_seek ( dvdcss_t dvdcss, int i_blocks, int i_flags )
{
/* title cracking method is too slow to be used at each seek */
if( ( ( i_flags & DVDCSS_SEEK_MPEG )
- && ( dvdcss->i_method != DVDCSS_METHOD_TITLE ) )
+ && ( dvdcss->i_method != DVDCSS_METHOD_TITLE ) )
|| ( i_flags & DVDCSS_SEEK_KEY ) )
{
/* check the title key */
- if( _dvdcss_title( dvdcss, i_blocks ) )
+ if( _dvdcss_title( dvdcss, i_blocks ) )
{
return -1;
}
@@ -407,31 +511,31 @@ extern int dvdcss_read ( dvdcss_t dvdcss, void *p_buffer,
if( ! memcmp( dvdcss->css.p_title_key, "\0\0\0\0\0", 5 ) )
{
- /* For what we believe is an unencrypted title,
- * check that there are no encrypted blocks */
+ /* For what we believe is an unencrypted title,
+ * check that there are no encrypted blocks */
for( i_index = i_ret; i_index; i_index-- )
{
- if( ((u8*)p_buffer)[0x14] & 0x30 )
+ if( ((uint8_t*)p_buffer)[0x14] & 0x30 )
{
_dvdcss_error( dvdcss, "no key but found encrypted block" );
/* Only return the initial range of unscrambled blocks? */
/* or fail completely? return 0; */
- break;
+ break;
}
- p_buffer = (void *) ((u8 *)p_buffer + DVDCSS_BLOCK_SIZE);
+ p_buffer = (void *) ((uint8_t *)p_buffer + DVDCSS_BLOCK_SIZE);
}
}
- else
+ else
{
/* Decrypt the blocks we managed to read */
for( i_index = i_ret; i_index; i_index-- )
- {
- _dvdcss_unscramble( dvdcss->css.p_title_key, p_buffer );
- ((u8*)p_buffer)[0x14] &= 0x8f;
- p_buffer = (void *) ((u8 *)p_buffer + DVDCSS_BLOCK_SIZE);
- }
+ {
+ _dvdcss_unscramble( dvdcss->css.p_title_key, p_buffer );
+ ((uint8_t*)p_buffer)[0x14] &= 0x8f;
+ p_buffer = (void *) ((uint8_t *)p_buffer + DVDCSS_BLOCK_SIZE);
+ }
}
-
+
return i_ret;
}
@@ -502,9 +606,9 @@ extern int dvdcss_readv ( dvdcss_t dvdcss, void *p_iovec,
}
_dvdcss_unscramble( dvdcss->css.p_title_key, iov_base );
- ((u8*)iov_base)[0x14] &= 0x8f;
+ ((uint8_t*)iov_base)[0x14] &= 0x8f;
- iov_base = (void *) ((u8*)iov_base + DVDCSS_BLOCK_SIZE);
+ iov_base = (void *) ((uint8_t*)iov_base + DVDCSS_BLOCK_SIZE);
iov_len -= DVDCSS_BLOCK_SIZE;
}