ref: ec1bd09bf4768c9641363c13af2248edd0e24c91
parent: c8e2bf595185afd6835852e78e2318e9c9cbc049
author: Sam Hocevar <sam@videolan.org>
date: Sun Nov 24 12:34:23 EST 2002
* ./src/css.c, ./src/libdvdcss.c: applied a to cache title keys on disk.
--- a/src/css.c
+++ b/src/css.c
@@ -2,7 +2,7 @@
* css.c: Functions for DVD authentication and descrambling
*****************************************************************************
* Copyright (C) 1999-2001 VideoLAN
- * $Id: css.c,v 1.19 2002/11/14 12:38:57 gbazin Exp $
+ * $Id: css.c,v 1.20 2002/11/24 17:34:23 sam Exp $
*
* Author: St�phane Borel <stef@via.ecp.fr>
* H�kan Hjort <d95hjort@dtek.chalmers.se>
@@ -38,6 +38,10 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <sys/param.h>
+#include <fcntl.h>
#include "dvdcss/dvdcss.h"
@@ -275,10 +279,11 @@
*****************************************************************************/
int _dvdcss_title ( dvdcss_t dvdcss, int i_block )
{
+ char * psz_cachefile = NULL;
dvd_title_t *p_title;
dvd_title_t *p_newtitle;
dvd_key_t p_title_key;
- int i_ret;
+ int i_fd, i_ret = -1, b_cache = 0;
if( ! dvdcss->b_scrambled )
{
@@ -302,18 +307,54 @@
return 0;
}
- /* Crack or decrypt CSS title key for current VTS */
- i_ret = _dvdcss_titlekey( dvdcss, i_block, p_title_key );
+ /* Check whether the key is in our disk cache */
+ if( dvdcss->psz_cachefile[0] )
+ {
+ /* XXX: be careful, we use sprintf and not snprintf */
+ sprintf( dvdcss->psz_block, "%0.10x", i_block );
+ i_fd = open( dvdcss->psz_cachefile, O_RDONLY );
+ b_cache = 1;
+ if( i_fd >= 0 )
+ {
+ if( read( i_fd, p_title_key, 5 ) == 5 )
+ {
+ _dvdcss_debug( dvdcss, "key found in cache" );
+ /* Don't try to save it again */
+ b_cache = 0;
+ i_ret = 1;
+ }
+ close( i_fd );
+ }
+ }
+
+ /* Crack or decrypt CSS title key for current VTS */
if( i_ret < 0 )
{
- _dvdcss_error( dvdcss, "fatal error in vts css key" );
- return i_ret;
+ i_ret = _dvdcss_titlekey( dvdcss, i_block, p_title_key );
+
+ if( i_ret < 0 )
+ {
+ _dvdcss_error( dvdcss, "fatal error in vts css key" );
+ return i_ret;
+ }
+
+ if( i_ret == 0 )
+ {
+ _dvdcss_debug( dvdcss, "unencrypted title" );
+ /* We cache this anyway, so we don't need to check again. */
+ }
}
- else if( i_ret == 0 )
+
+ /* Key is valid, we store it on disk. */
+ if( b_cache )
{
- _dvdcss_debug( dvdcss, "unencrypted title" );
- /* Still store this in the cache, so we don't need to check again. */
+ i_fd = open( dvdcss->psz_cachefile, O_RDWR|O_CREAT|O_EXCL, 0644 );
+ if( i_fd >= 0 )
+ {
+ write( i_fd, p_title_key, 5 );
+ close( i_fd );
+ }
}
/* Find our spot in the list */
@@ -1451,7 +1492,7 @@
return 1;
}
- if( i_encrypted == 0 )
+ if( i_encrypted == 0 && i_reads > 0 )
{
memset( p_titlekey, 0, KEY_SIZE );
_dvdcss_debug( dvdcss, "file was unscrambled" );
--- a/src/device.c
+++ b/src/device.c
@@ -2,7 +2,7 @@
* device.h: DVD device access
*****************************************************************************
* Copyright (C) 1998-2002 VideoLAN
- * $Id: device.c,v 1.6 2002/10/19 09:53:33 gbazin Exp $
+ * $Id: device.c,v 1.7 2002/11/24 17:34:23 sam Exp $
*
* Authors: St�phane Borel <stef@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
@@ -33,6 +33,7 @@
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/param.h>
#include <fcntl.h>
#ifdef HAVE_UNISTD_H
--- a/src/error.c
+++ b/src/error.c
@@ -2,7 +2,7 @@
* error.c: error management functions
*****************************************************************************
* Copyright (C) 1998-2002 VideoLAN
- * $Id: error.c,v 1.2 2002/08/10 14:27:26 sam Exp $
+ * $Id: error.c,v 1.3 2002/11/24 17:34:23 sam Exp $
*
* Author: Samuel Hocevar <sam@zoy.org>
*
@@ -24,6 +24,7 @@
#include "config.h"
#include <stdio.h>
+#include <sys/param.h>
#include "dvdcss/dvdcss.h"
--- a/src/libdvdcss.c
+++ b/src/libdvdcss.c
@@ -5,7 +5,7 @@
* H�kan Hjort <d95hjort@dtek.chalmers.se>
*
* Copyright (C) 1998-2002 VideoLAN
- * $Id: libdvdcss.c,v 1.19 2002/10/18 18:48:59 sam Exp $
+ * $Id: libdvdcss.c,v 1.20 2002/11/24 17:34:23 sam Exp $
*
* 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
@@ -79,6 +79,11 @@
*
* \li \b DVDCSS_RAW_DEVICE: specify the raw device to use.
*
+ * \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.
*/
/*
@@ -91,7 +96,9 @@
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
+#include <sys/param.h>
#include <fcntl.h>
+#include <errno.h>
#ifdef HAVE_UNISTD_H
# include <unistd.h>
@@ -137,6 +144,7 @@
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
@@ -162,6 +170,7 @@
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;
@@ -209,6 +218,23 @@
}
/*
+ * 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;
+ }
+ }
+
+ /*
* Open device
*/
i_ret = _dvdcss_open( dvdcss );
@@ -260,6 +286,99 @@
_dvdcss_raw_open( dvdcss, psz_raw_device );
}
#endif
+
+ /* If the cache is enabled, extract a unique disc ID */
+ if( psz_cache )
+ {
+ u8 p_sector[DVDCSS_BLOCK_SIZE];
+ unsigned char psz_debug[PATH_MAX+30];
+ unsigned char * psz_data;
+ int i;
+
+ /* 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,
+ "%0.2X%0.2X%0.2X%0.2X%0.2X%0.2X%0.2X%0.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 );
+ i_ret = mkdir( dvdcss->psz_cachefile, 0755 );
+ 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 );
+ i_ret = mkdir( dvdcss->psz_cachefile, 0755 );
+ 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;
}
--- a/src/libdvdcss.h
+++ b/src/libdvdcss.h
@@ -2,7 +2,7 @@
* private.h: private DVD reading library data
*****************************************************************************
* Copyright (C) 1998-2001 VideoLAN
- * $Id: libdvdcss.h,v 1.5 2002/10/18 18:48:59 sam Exp $
+ * $Id: libdvdcss.h,v 1.6 2002/11/24 17:34:23 sam Exp $
*
* Authors: St�phane Borel <stef@via.ecp.fr>
* Samuel Hocevar <sam@zoy.org>
@@ -46,6 +46,10 @@
int b_ioctls;
int b_scrambled;
dvd_title_t *p_titles;
+
+ /* Key cache directory and pointer to the filename */
+ char psz_cachefile[PATH_MAX];
+ char * psz_block;
/* Error management */
char * psz_error;