shithub: libdvdcss

Download patch

ref: 8ac62497bbcd7a64fdc94e062d5ccae18756c7df
parent: ba862c3860586c3d7248b6bd665440fe791d6c1a
author: Sam Hocevar <sam@videolan.org>
date: Thu Dec 19 11:50:50 EST 2002

* ./src/device.c: seek() calls don't do anything if we're already at the
    right position.
  * ./src/device.c: we now handle partial reads.


--- 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.13 2002/12/19 15:36:04 sam Exp $
+ * $Id: device.c,v 1.14 2002/12/19 16:50:50 sam Exp $
  *
  * Authors: St�phane Borel <stef@via.ecp.fr>
  *          Samuel Hocevar <sam@zoy.org>
@@ -426,6 +426,12 @@
 {
     off_t   i_seek;
 
+    if( dvdcss->i_pos == i_blocks )
+    {
+        /* We are already in position */
+        return i_blocks;
+    }
+
     i_seek = lseek( dvdcss->i_read_fd,
                     (off_t)i_blocks * (off_t)DVDCSS_BLOCK_SIZE, SEEK_SET );
 
@@ -432,6 +438,8 @@
     if( i_seek < 0 )
     {
         _dvdcss_error( dvdcss, "seek error" );
+        dvdcss->i_pos = -1;
+        return i_seek;
     }
 
     dvdcss->i_pos = i_seek / DVDCSS_BLOCK_SIZE;
@@ -448,6 +456,12 @@
 #   define INVALID_SET_FILE_POINTER ((DWORD)-1)
 #endif
 
+    if( dvdcss->i_pos == i_blocks )
+    {
+        /* We are already in position */
+        return i_blocks;
+    }
+
     li_seek.QuadPart = (LONGLONG)i_blocks * DVDCSS_BLOCK_SIZE;
 
     li_seek.LowPart = SetFilePointer( (HANDLE) dvdcss->i_fd,
@@ -456,7 +470,8 @@
     if( (li_seek.LowPart == INVALID_SET_FILE_POINTER)
         && GetLastError() != NO_ERROR)
     {
-        li_seek.QuadPart = -DVDCSS_BLOCK_SIZE;
+        dvdcss->i_pos = -1;
+        return -1;
     }
 
     dvdcss->i_pos = li_seek.QuadPart / DVDCSS_BLOCK_SIZE;
@@ -470,6 +485,12 @@
     char sz_buf[ DVDCSS_BLOCK_SIZE ];
     struct w32_aspidev *fd = (struct w32_aspidev *) dvdcss->i_fd;
 
+    if( dvdcss->i_pos == i_blocks )
+    {
+        /* We are already in position */
+        return i_blocks;
+    }
+
     i_old_blocks = fd->i_blocks;
     fd->i_blocks = i_blocks;
 
@@ -476,6 +497,7 @@
     if( aspi_read_internal( dvdcss->i_fd, sz_buf, 1 ) == -1 )
     {
         fd->i_blocks = i_old_blocks;
+        dvdcss->i_pos = -1;
         return -1;
     }
 
@@ -493,7 +515,6 @@
 static int libc_read ( dvdcss_t dvdcss, void *p_buffer, int i_blocks )
 {
     off_t i_ret;
-    int   i_read;
 
     i_ret = read( dvdcss->i_read_fd, p_buffer,
                   (off_t)i_blocks * DVDCSS_BLOCK_SIZE );
@@ -501,6 +522,7 @@
     if( i_ret < 0 )
     {
         _dvdcss_error( dvdcss, "read error" );
+        dvdcss->i_pos = -1;
         return i_ret;
     }
 
@@ -507,13 +529,21 @@
     /* Handle partial reads */
     if( i_ret != (off_t)i_blocks * DVDCSS_BLOCK_SIZE )
     {
-        /* TODO */
-    }
+        int i_seek;
 
-    i_read = i_ret / DVDCSS_BLOCK_SIZE;
-    dvdcss->i_pos += i_read;
+        dvdcss->i_pos = -1;
+        i_seek = libc_seek( dvdcss, i_ret / DVDCSS_BLOCK_SIZE );
+        if( i_seek < 0 )
+        {
+            return i_seek;
+        }
 
-    return i_read;
+        /* We have to return now so that i_pos isn't clobbered */
+        return i_ret / DVDCSS_BLOCK_SIZE;
+    }
+
+    dvdcss->i_pos += i_ret / DVDCSS_BLOCK_SIZE;
+    return i_ret / DVDCSS_BLOCK_SIZE;
 }
 
 #if defined( WIN32 )
@@ -525,6 +555,7 @@
               i_blocks * DVDCSS_BLOCK_SIZE,
               (LPDWORD)&i_bytes, NULL ) )
     {
+        dvdcss->i_pos = -1;
         return -1;
     }
 
@@ -538,6 +569,7 @@
 
     if( i_read < 0 )
     {
+        dvdcss->i_pos = -1;
         return i_read;
     }
 
@@ -576,6 +608,7 @@
              * We won't even bother returning the reads that went ok,
              * and as in the posix spec the file postition is left
              * unspecified after a failure */
+            dvdcss->i_pos = -1;
             return -1;
         }
 
@@ -585,7 +618,16 @@
         {
             /* We reached the end of the file or a signal interrupted
              * the read. Return a partial read. */
-            /* XXX: handle this partial read correctly */
+            int i_seek;
+
+            dvdcss->i_pos = -1;
+            i_seek = libc_seek( dvdcss, i_total / DVDCSS_BLOCK_SIZE );
+            if( i_seek < 0 )
+            {
+                return i_seek;
+            }
+
+            /* We have to return now so that i_pos isn't clobbered */
             return i_total / DVDCSS_BLOCK_SIZE;
         }
     }
@@ -597,6 +639,7 @@
 
     if( i_read < 0 )
     {
+        dvdcss->i_pos = -1;
         return i_read;
     }
 
@@ -628,6 +671,7 @@
         if( !dvdcss->p_readv_buffer )
         {
             _dvdcss_error( dvdcss, " failed (readv)" );
+            dvdcss->i_pos = -1;
             return -1;
         }
     }
@@ -650,6 +694,7 @@
             /* The read failed... too bad.
              * As in the posix spec the file postition is left
              * unspecified after a failure */
+            dvdcss->i_pos = -1;
             return -1;
         }
         i_blocks_read = i_bytes / DVDCSS_BLOCK_SIZE;
@@ -662,6 +707,7 @@
         if( i_blocks_read < 0 )
         {
             /* See above */
+            dvdcss->i_pos = -1;
             return -1;
         }
     }