Mercurial > mplayer.hg
annotate libdvdcss/device.c @ 36260:a2750366a255
stream/tcp: Check that host object has the right AF before connect
Avoid trying bogus IPv6 adresses on systems that only
have gethostbyname function. Currently we would copy the
IPv4 address into the first part of the IPv6 and then try
to connect to that. The connection attempt can take a long
time.
Tested-by: Erik Auerswald >auerswal unix-ag uni-kl de<
Patch-by: >aplattner nvidia com<
author | al |
---|---|
date | Thu, 11 Jul 2013 22:08:33 +0000 |
parents | 691431d2289e |
children |
rev | line source |
---|---|
20613 | 1 /***************************************************************************** |
2 * device.h: DVD device access | |
3 ***************************************************************************** | |
4 * Copyright (C) 1998-2006 VideoLAN | |
5 * | |
27442 | 6 * Authors: Stéphane Borel <stef@via.ecp.fr> |
20613 | 7 * Sam Hocevar <sam@zoy.org> |
27442 | 8 * Håkan Hjort <d95hjort@dtek.chalmers.se> |
20613 | 9 * |
31098
9e9595c779cf
libdvdcss: cosmetics: Fix FSF address and program name in license headers.
diego
parents:
27442
diff
changeset
|
10 * This library is free software; you can redistribute it and/or modify |
20613 | 11 * it under the terms of the GNU General Public License as published by |
12 * the Free Software Foundation; either version 2 of the License, or | |
13 * (at your option) any later version. | |
14 * | |
31098
9e9595c779cf
libdvdcss: cosmetics: Fix FSF address and program name in license headers.
diego
parents:
27442
diff
changeset
|
15 * This library is distributed in the hope that it will be useful, |
20613 | 16 * but WITHOUT ANY WARRANTY; without even the implied warranty of |
17 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
18 * GNU General Public License for more details. | |
19 * | |
31098
9e9595c779cf
libdvdcss: cosmetics: Fix FSF address and program name in license headers.
diego
parents:
27442
diff
changeset
|
20 * You should have received a copy of the GNU General Public License along |
9e9595c779cf
libdvdcss: cosmetics: Fix FSF address and program name in license headers.
diego
parents:
27442
diff
changeset
|
21 * with this library; if not, write to the Free Software Foundation, Inc., |
9e9595c779cf
libdvdcss: cosmetics: Fix FSF address and program name in license headers.
diego
parents:
27442
diff
changeset
|
22 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
20613 | 23 *****************************************************************************/ |
24 | |
25 /***************************************************************************** | |
26 * Preamble | |
27 *****************************************************************************/ | |
28 #include "config.h" | |
29 | |
30 #include <stdio.h> | |
31 #include <stdlib.h> | |
32 #include <string.h> | |
33 #ifdef HAVE_ERRNO_H | |
34 # include <errno.h> | |
35 #endif | |
36 #include <sys/types.h> | |
37 #include <sys/stat.h> | |
38 #ifdef HAVE_SYS_PARAM_H | |
39 # include <sys/param.h> | |
40 #endif | |
41 #include <fcntl.h> | |
42 | |
43 #ifdef HAVE_UNISTD_H | |
44 # include <unistd.h> | |
45 #endif | |
46 | |
47 #ifdef HAVE_LIMITS_H | |
48 # include <limits.h> | |
49 #endif | |
50 | |
51 #ifdef DARWIN_DVD_IOCTL | |
52 # include <paths.h> | |
53 # include <CoreFoundation/CoreFoundation.h> | |
54 # include <IOKit/IOKitLib.h> | |
55 # include <IOKit/IOBSD.h> | |
56 # include <IOKit/storage/IOMedia.h> | |
57 # include <IOKit/storage/IOCDMedia.h> | |
58 # include <IOKit/storage/IODVDMedia.h> | |
59 #endif | |
60 | |
35952 | 61 #ifdef __OS2__ |
31099
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
62 # define INCL_DOS |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
63 # define INCL_DOSDEVIOCTL |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
64 # include <os2.h> |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
65 # include <io.h> /* setmode() */ |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
66 # include <fcntl.h> /* O_BINARY */ |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
67 #endif |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
68 |
20613 | 69 #include "dvdcss/dvdcss.h" |
70 | |
71 #include "common.h" | |
72 #include "css.h" | |
73 #include "libdvdcss.h" | |
74 #include "ioctl.h" | |
75 #include "device.h" | |
76 | |
77 /***************************************************************************** | |
78 * Device reading prototypes | |
79 *****************************************************************************/ | |
80 static int libc_open ( dvdcss_t, char const * ); | |
81 static int libc_seek ( dvdcss_t, int ); | |
82 static int libc_read ( dvdcss_t, void *, int ); | |
83 static int libc_readv ( dvdcss_t, struct iovec *, int ); | |
84 | |
85 #ifdef WIN32 | |
86 static int win2k_open ( dvdcss_t, char const * ); | |
87 static int aspi_open ( dvdcss_t, char const * ); | |
88 static int win2k_seek ( dvdcss_t, int ); | |
89 static int aspi_seek ( dvdcss_t, int ); | |
90 static int win2k_read ( dvdcss_t, void *, int ); | |
91 static int aspi_read ( dvdcss_t, void *, int ); | |
92 static int win_readv ( dvdcss_t, struct iovec *, int ); | |
93 | |
94 static int aspi_read_internal ( int, void *, int ); | |
35952 | 95 #elif defined( __OS2__ ) |
31099
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
96 static int os2_open ( dvdcss_t, char const * ); |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
97 /* just use macros for libc */ |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
98 # define os2_seek libc_seek |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
99 # define os2_read libc_read |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
100 # define os2_readv libc_readv |
20613 | 101 #endif |
102 | |
103 int _dvdcss_use_ioctls( dvdcss_t dvdcss ) | |
104 { | |
105 #if defined( WIN32 ) | |
106 if( dvdcss->b_file ) | |
107 { | |
108 return 0; | |
109 } | |
110 | |
111 /* FIXME: implement this for Windows */ | |
112 if( WIN2K ) | |
113 { | |
114 return 1; | |
115 } | |
116 else | |
117 { | |
118 return 1; | |
119 } | |
35952 | 120 #elif defined( __OS2__ ) |
31099
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
121 ULONG ulMode; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
122 |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
123 if( DosQueryFHState( dvdcss->i_fd, &ulMode ) != 0 ) |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
124 return 1; /* What to do? Be conservative and try to use the ioctls */ |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
125 |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
126 if( ulMode & OPEN_FLAGS_DASD ) |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
127 return 1; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
128 |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
129 return 0; |
20613 | 130 #else |
131 struct stat fileinfo; | |
132 int ret; | |
133 | |
134 ret = fstat( dvdcss->i_fd, &fileinfo ); | |
135 if( ret < 0 ) | |
136 { | |
137 return 1; /* What to do? Be conservative and try to use the ioctls */ | |
138 } | |
139 | |
140 /* Complete this list and check that we test for the right things | |
141 * (I've assumed for all OSs that 'r', (raw) device, are char devices | |
142 * and those that don't contain/use an 'r' in the name are block devices) | |
143 * | |
144 * Linux needs a block device | |
145 * Solaris needs a char device | |
146 * Darwin needs a char device | |
147 * OpenBSD needs a char device | |
148 * NetBSD needs a char device | |
149 * FreeBSD can use either the block or the char device | |
150 */ | |
151 | |
152 /* Check if this is a block/char device */ | |
153 if( S_ISBLK( fileinfo.st_mode ) || | |
154 S_ISCHR( fileinfo.st_mode ) ) | |
155 { | |
156 return 1; | |
157 } | |
158 else | |
159 { | |
160 return 0; | |
161 } | |
162 #endif | |
163 } | |
164 | |
165 void _dvdcss_check ( dvdcss_t dvdcss ) | |
166 { | |
167 #if defined( WIN32 ) | |
168 DWORD drives; | |
169 int i; | |
170 #elif defined( DARWIN_DVD_IOCTL ) | |
171 io_object_t next_media; | |
172 mach_port_t master_port; | |
173 kern_return_t kern_result; | |
174 io_iterator_t media_iterator; | |
175 CFMutableDictionaryRef classes_to_match; | |
35952 | 176 #elif defined( __OS2__ ) |
31099
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
177 #pragma pack( 1 ) |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
178 struct |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
179 { |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
180 BYTE bCmdInfo; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
181 BYTE bDrive; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
182 } param; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
183 |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
184 struct |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
185 { |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
186 BYTE abEBPB[31]; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
187 USHORT usCylinders; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
188 BYTE bDevType; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
189 USHORT usDevAttr; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
190 } data; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
191 #pragma pack() |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
192 |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
193 ULONG ulParamLen; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
194 ULONG ulDataLen; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
195 ULONG rc; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
196 |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
197 int i; |
20613 | 198 #else |
199 char *ppsz_devices[] = { "/dev/dvd", "/dev/cdrom", "/dev/hdc", NULL }; | |
200 int i, i_fd; | |
201 #endif | |
202 | |
203 /* If the device name is non-null, return */ | |
204 if( dvdcss->psz_device[0] ) | |
205 { | |
206 return; | |
207 } | |
208 | |
209 #if defined( WIN32 ) | |
210 drives = GetLogicalDrives(); | |
211 | |
212 for( i = 0; drives; i++ ) | |
213 { | |
214 char psz_device[5]; | |
215 DWORD cur = 1 << i; | |
216 UINT i_ret; | |
217 | |
218 if( (drives & cur) == 0 ) | |
219 { | |
220 continue; | |
221 } | |
222 drives &= ~cur; | |
223 | |
224 sprintf( psz_device, "%c:\\", 'A' + i ); | |
225 i_ret = GetDriveType( psz_device ); | |
226 if( i_ret != DRIVE_CDROM ) | |
227 { | |
228 continue; | |
229 } | |
230 | |
231 /* Remove trailing backslash */ | |
232 psz_device[2] = '\0'; | |
233 | |
35952 | 234 /* FIXME: we want to differentiate between CD and DVD drives |
20613 | 235 * using DeviceIoControl() */ |
236 print_debug( dvdcss, "defaulting to drive `%s'", psz_device ); | |
237 free( dvdcss->psz_device ); | |
238 dvdcss->psz_device = strdup( psz_device ); | |
239 return; | |
240 } | |
241 #elif defined( DARWIN_DVD_IOCTL ) | |
242 | |
243 kern_result = IOMasterPort( MACH_PORT_NULL, &master_port ); | |
244 if( kern_result != KERN_SUCCESS ) | |
245 { | |
246 return; | |
247 } | |
248 | |
249 classes_to_match = IOServiceMatching( kIODVDMediaClass ); | |
250 if( classes_to_match == NULL ) | |
251 { | |
252 return; | |
253 } | |
254 | |
255 CFDictionarySetValue( classes_to_match, CFSTR( kIOMediaEjectableKey ), | |
256 kCFBooleanTrue ); | |
257 | |
258 kern_result = IOServiceGetMatchingServices( master_port, classes_to_match, | |
259 &media_iterator ); | |
260 if( kern_result != KERN_SUCCESS ) | |
261 { | |
262 return; | |
263 } | |
264 | |
265 next_media = IOIteratorNext( media_iterator ); | |
266 for( ; ; ) | |
267 { | |
268 char psz_buf[0x32]; | |
269 size_t i_pathlen; | |
270 CFTypeRef psz_path; | |
271 | |
272 next_media = IOIteratorNext( media_iterator ); | |
273 if( next_media == 0 ) | |
274 { | |
275 break; | |
276 } | |
277 | |
278 psz_path = IORegistryEntryCreateCFProperty( next_media, | |
279 CFSTR( kIOBSDNameKey ), | |
280 kCFAllocatorDefault, | |
281 0 ); | |
282 if( psz_path == NULL ) | |
283 { | |
284 IOObjectRelease( next_media ); | |
285 continue; | |
286 } | |
287 | |
288 snprintf( psz_buf, sizeof(psz_buf), "%s%c", _PATH_DEV, 'r' ); | |
289 i_pathlen = strlen( psz_buf ); | |
290 | |
291 if( CFStringGetCString( psz_path, | |
292 (char*)&psz_buf + i_pathlen, | |
293 sizeof(psz_buf) - i_pathlen, | |
294 kCFStringEncodingASCII ) ) | |
295 { | |
296 print_debug( dvdcss, "defaulting to drive `%s'", psz_buf ); | |
297 CFRelease( psz_path ); | |
298 IOObjectRelease( next_media ); | |
299 IOObjectRelease( media_iterator ); | |
300 free( dvdcss->psz_device ); | |
301 dvdcss->psz_device = strdup( psz_buf ); | |
302 return; | |
303 } | |
304 | |
305 CFRelease( psz_path ); | |
306 | |
307 IOObjectRelease( next_media ); | |
308 } | |
309 | |
310 IOObjectRelease( media_iterator ); | |
35952 | 311 #elif defined( __OS2__ ) |
31099
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
312 for( i = 0; i < 26; i++ ) |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
313 { |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
314 param.bCmdInfo = 0; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
315 param.bDrive = i; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
316 |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
317 rc = DosDevIOCtl( ( HFILE )-1, IOCTL_DISK, DSK_GETDEVICEPARAMS, |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
318 ¶m, sizeof( param ), &ulParamLen, |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
319 &data, sizeof( data ), &ulDataLen ); |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
320 |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
321 if( rc == 0 ) |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
322 { |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
323 /* Check for removable and for cylinders */ |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
324 if( ( data.usDevAttr & 1 ) == 0 && data.usCylinders == 0xFFFF ) |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
325 { |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
326 char psz_dvd[] = "A:"; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
327 |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
328 psz_dvd[0] += i; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
329 |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
330 print_debug( dvdcss, "defaulting to drive `%s'", psz_dvd ); |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
331 free( dvdcss->psz_device ); |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
332 dvdcss->psz_device = strdup( psz_dvd ); |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
333 return; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
334 } |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
335 } |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
336 } |
20613 | 337 #else |
338 for( i = 0; ppsz_devices[i]; i++ ) | |
339 { | |
340 i_fd = open( ppsz_devices[i], 0 ); | |
341 if( i_fd != -1 ) | |
342 { | |
343 print_debug( dvdcss, "defaulting to drive `%s'", ppsz_devices[i] ); | |
344 close( i_fd ); | |
345 free( dvdcss->psz_device ); | |
346 dvdcss->psz_device = strdup( ppsz_devices[i] ); | |
347 return; | |
348 } | |
349 } | |
350 #endif | |
351 | |
352 print_error( dvdcss, "could not find a suitable default drive" ); | |
353 } | |
354 | |
355 int _dvdcss_open ( dvdcss_t dvdcss ) | |
356 { | |
357 char const *psz_device = dvdcss->psz_device; | |
358 | |
359 print_debug( dvdcss, "opening target `%s'", psz_device ); | |
360 | |
361 #if defined( WIN32 ) | |
362 dvdcss->b_file = 1; | |
363 /* If device is "X:" or "X:\", we are not actually opening a file. */ | |
364 if (psz_device[0] && psz_device[1] == ':' && | |
365 (!psz_device[2] || (psz_device[2] == '\\' && !psz_device[3]))) | |
366 dvdcss->b_file = 0; | |
367 | |
368 /* Initialize readv temporary buffer */ | |
369 dvdcss->p_readv_buffer = NULL; | |
370 dvdcss->i_readv_buf_size = 0; | |
371 | |
372 if( !dvdcss->b_file && WIN2K ) | |
373 { | |
374 print_debug( dvdcss, "using Win2K API for access" ); | |
375 dvdcss->pf_seek = win2k_seek; | |
376 dvdcss->pf_read = win2k_read; | |
377 dvdcss->pf_readv = win_readv; | |
378 return win2k_open( dvdcss, psz_device ); | |
379 } | |
380 else if( !dvdcss->b_file ) | |
381 { | |
382 print_debug( dvdcss, "using ASPI for access" ); | |
383 dvdcss->pf_seek = aspi_seek; | |
384 dvdcss->pf_read = aspi_read; | |
385 dvdcss->pf_readv = win_readv; | |
386 return aspi_open( dvdcss, psz_device ); | |
387 } | |
388 else | |
35952 | 389 #elif defined( __OS2__ ) |
31099
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
390 /* If device is "X:" or "X:\", we are not actually opening a file. */ |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
391 if( psz_device[0] && psz_device[1] == ':' && |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
392 ( !psz_device[2] || ( psz_device[2] == '\\' && !psz_device[3] ) ) ) |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
393 { |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
394 print_debug( dvdcss, "using OS2 API for access" ); |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
395 dvdcss->pf_seek = os2_seek; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
396 dvdcss->pf_read = os2_read; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
397 dvdcss->pf_readv = os2_readv; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
398 return os2_open( dvdcss, psz_device ); |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
399 } |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
400 else |
20613 | 401 #endif |
402 { | |
403 print_debug( dvdcss, "using libc for access" ); | |
404 dvdcss->pf_seek = libc_seek; | |
405 dvdcss->pf_read = libc_read; | |
406 dvdcss->pf_readv = libc_readv; | |
407 return libc_open( dvdcss, psz_device ); | |
408 } | |
409 } | |
410 | |
35952 | 411 #ifdef DVDCSS_RAW_OPEN |
20613 | 412 int _dvdcss_raw_open ( dvdcss_t dvdcss, char const *psz_device ) |
413 { | |
414 dvdcss->i_raw_fd = open( psz_device, 0 ); | |
415 | |
416 if( dvdcss->i_raw_fd == -1 ) | |
417 { | |
418 print_debug( dvdcss, "cannot open %s (%s)", | |
419 psz_device, strerror(errno) ); | |
420 print_error( dvdcss, "failed to open raw device, but continuing" ); | |
421 return -1; | |
422 } | |
423 else | |
424 { | |
425 dvdcss->i_read_fd = dvdcss->i_raw_fd; | |
426 } | |
427 | |
428 return 0; | |
429 } | |
430 #endif | |
431 | |
432 int _dvdcss_close ( dvdcss_t dvdcss ) | |
433 { | |
434 #if defined( WIN32 ) | |
435 if( dvdcss->b_file ) | |
436 { | |
437 close( dvdcss->i_fd ); | |
438 } | |
439 else if( WIN2K ) | |
440 { | |
441 CloseHandle( (HANDLE) dvdcss->i_fd ); | |
442 } | |
443 else /* ASPI */ | |
444 { | |
445 struct w32_aspidev *fd = (struct w32_aspidev *) dvdcss->i_fd; | |
446 | |
35952 | 447 /* Unload ASPI and free w32_aspidev structure */ |
20613 | 448 FreeLibrary( (HMODULE) fd->hASPI ); |
449 free( (void*) dvdcss->i_fd ); | |
450 } | |
451 | |
452 /* Free readv temporary buffer */ | |
453 if( dvdcss->p_readv_buffer ) | |
454 { | |
455 free( dvdcss->p_readv_buffer ); | |
456 dvdcss->p_readv_buffer = NULL; | |
457 dvdcss->i_readv_buf_size = 0; | |
458 } | |
459 | |
460 return 0; | |
461 #else | |
462 close( dvdcss->i_fd ); | |
463 | |
35952 | 464 #ifdef DVDCSS_RAW_OPEN |
20613 | 465 if( dvdcss->i_raw_fd >= 0 ) |
466 { | |
467 close( dvdcss->i_raw_fd ); | |
468 dvdcss->i_raw_fd = -1; | |
469 } | |
31099
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
470 #endif |
20613 | 471 |
472 return 0; | |
473 #endif | |
474 } | |
475 | |
476 /* Following functions are local */ | |
477 | |
478 /***************************************************************************** | |
479 * Open commands. | |
480 *****************************************************************************/ | |
481 static int libc_open ( dvdcss_t dvdcss, char const *psz_device ) | |
482 { | |
483 dvdcss->i_fd = dvdcss->i_read_fd = open( psz_device, O_BINARY ); | |
484 | |
485 if( dvdcss->i_fd == -1 ) | |
486 { | |
487 print_debug( dvdcss, "cannot open %s (%s)", | |
488 psz_device, strerror(errno) ); | |
489 print_error( dvdcss, "failed to open device" ); | |
490 return -1; | |
491 } | |
492 | |
493 dvdcss->i_pos = 0; | |
494 | |
495 return 0; | |
496 } | |
497 | |
498 #if defined( WIN32 ) | |
499 static int win2k_open ( dvdcss_t dvdcss, char const *psz_device ) | |
500 { | |
501 char psz_dvd[7]; | |
34178
3c0cf739f1e1
libdvdcss: consistently use snprintf() instead of _snprintf()
diego
parents:
31099
diff
changeset
|
502 snprintf( psz_dvd, 7, "\\\\.\\%c:", psz_device[0] ); |
20613 | 503 |
504 /* To work around an M$ bug in IOCTL_DVD_READ_STRUCTURE, we need read | |
505 * _and_ write access to the device (so we can make SCSI Pass Through | |
506 * Requests). Unfortunately this is only allowed if you have | |
35952 | 507 * administrator privileges so we allow for a fallback method with |
20613 | 508 * only read access to the device (in this case ioctl_ReadCopyright() |
509 * won't send back the right result). | |
510 * (See Microsoft Q241374: Read and Write Access Required for SCSI | |
511 * Pass Through Requests) */ | |
512 dvdcss->i_fd = (int) | |
513 CreateFile( psz_dvd, GENERIC_READ | GENERIC_WRITE, | |
514 FILE_SHARE_READ | FILE_SHARE_WRITE, | |
515 NULL, OPEN_EXISTING, | |
516 FILE_FLAG_RANDOM_ACCESS, NULL ); | |
517 | |
518 if( (HANDLE) dvdcss->i_fd == INVALID_HANDLE_VALUE ) | |
519 dvdcss->i_fd = (int) | |
520 CreateFile( psz_dvd, GENERIC_READ, FILE_SHARE_READ, | |
521 NULL, OPEN_EXISTING, | |
522 FILE_FLAG_RANDOM_ACCESS, NULL ); | |
523 | |
524 if( (HANDLE) dvdcss->i_fd == INVALID_HANDLE_VALUE ) | |
525 { | |
526 print_error( dvdcss, "failed opening device" ); | |
527 return -1; | |
528 } | |
529 | |
530 dvdcss->i_pos = 0; | |
531 | |
532 return 0; | |
533 } | |
534 | |
535 static int aspi_open( dvdcss_t dvdcss, char const * psz_device ) | |
536 { | |
537 HMODULE hASPI; | |
538 DWORD dwSupportInfo; | |
539 struct w32_aspidev *fd; | |
540 int i, j, i_hostadapters; | |
541 GETASPI32SUPPORTINFO lpGetSupport; | |
542 SENDASPI32COMMAND lpSendCommand; | |
543 char c_drive = psz_device[0]; | |
544 | |
35952 | 545 /* load ASPI and init w32_aspidev structure */ |
20613 | 546 hASPI = LoadLibrary( "wnaspi32.dll" ); |
547 if( hASPI == NULL ) | |
548 { | |
549 print_error( dvdcss, "unable to load wnaspi32.dll" ); | |
550 return -1; | |
551 } | |
552 | |
553 lpGetSupport = (GETASPI32SUPPORTINFO) GetProcAddress( hASPI, "GetASPI32SupportInfo" ); | |
554 lpSendCommand = (SENDASPI32COMMAND) GetProcAddress( hASPI, "SendASPI32Command" ); | |
555 | |
556 if(lpGetSupport == NULL || lpSendCommand == NULL ) | |
557 { | |
35952 | 558 print_error( dvdcss, "unable to get ASPI function pointers" ); |
20613 | 559 FreeLibrary( hASPI ); |
560 return -1; | |
561 } | |
562 | |
563 dwSupportInfo = lpGetSupport(); | |
564 | |
565 if( HIBYTE( LOWORD ( dwSupportInfo ) ) == SS_NO_ADAPTERS ) | |
566 { | |
567 print_error( dvdcss, "no ASPI adapters found" ); | |
568 FreeLibrary( hASPI ); | |
569 return -1; | |
570 } | |
571 | |
572 if( HIBYTE( LOWORD ( dwSupportInfo ) ) != SS_COMP ) | |
573 { | |
35952 | 574 print_error( dvdcss, "unable to initialize ASPI layer" ); |
20613 | 575 FreeLibrary( hASPI ); |
576 return -1; | |
577 } | |
578 | |
579 i_hostadapters = LOBYTE( LOWORD( dwSupportInfo ) ); | |
580 if( i_hostadapters == 0 ) | |
581 { | |
582 print_error( dvdcss, "no ASPI adapters ready" ); | |
583 FreeLibrary( hASPI ); | |
584 return -1; | |
585 } | |
586 | |
587 fd = malloc( sizeof( struct w32_aspidev ) ); | |
588 if( fd == NULL ) | |
589 { | |
590 print_error( dvdcss, "not enough memory" ); | |
591 FreeLibrary( hASPI ); | |
592 return -1; | |
593 } | |
594 | |
595 fd->i_blocks = 0; | |
596 fd->hASPI = (long) hASPI; | |
597 fd->lpSendCommand = lpSendCommand; | |
598 | |
599 c_drive = c_drive > 'Z' ? c_drive - 'a' : c_drive - 'A'; | |
600 | |
601 for( i = 0; i < i_hostadapters; i++ ) | |
602 { | |
603 for( j = 0; j < 15; j++ ) | |
604 { | |
605 struct SRB_GetDiskInfo srbDiskInfo; | |
606 | |
607 srbDiskInfo.SRB_Cmd = SC_GET_DISK_INFO; | |
608 srbDiskInfo.SRB_HaId = i; | |
609 srbDiskInfo.SRB_Flags = 0; | |
610 srbDiskInfo.SRB_Hdr_Rsvd = 0; | |
611 srbDiskInfo.SRB_Target = j; | |
612 srbDiskInfo.SRB_Lun = 0; | |
613 | |
614 lpSendCommand( (void*) &srbDiskInfo ); | |
615 | |
616 if( (srbDiskInfo.SRB_Status == SS_COMP) && | |
617 (srbDiskInfo.SRB_Int13HDriveInfo == c_drive) ) | |
618 { | |
35952 | 619 /* Make sure this is a CD-ROM device */ |
620 struct SRB_GDEVBlock srbGDEVBlock = { 0 }; | |
20613 | 621 |
622 srbGDEVBlock.SRB_Cmd = SC_GET_DEV_TYPE; | |
623 srbGDEVBlock.SRB_HaId = i; | |
624 srbGDEVBlock.SRB_Target = j; | |
625 | |
626 lpSendCommand( (void*) &srbGDEVBlock ); | |
627 | |
628 if( ( srbGDEVBlock.SRB_Status == SS_COMP ) && | |
629 ( srbGDEVBlock.SRB_DeviceType == DTYPE_CDROM ) ) | |
630 { | |
631 fd->i_sid = MAKEWORD( i, j ); | |
632 dvdcss->i_fd = (int) fd; | |
633 dvdcss->i_pos = 0; | |
634 return 0; | |
635 } | |
636 else | |
637 { | |
638 free( (void*) fd ); | |
639 FreeLibrary( hASPI ); | |
35952 | 640 print_error( dvdcss,"this is not a CD-ROM drive" ); |
20613 | 641 return -1; |
642 } | |
643 } | |
644 } | |
645 } | |
646 | |
647 free( (void*) fd ); | |
648 FreeLibrary( hASPI ); | |
35952 | 649 print_error( dvdcss, "unable to get haid and target (ASPI)" ); |
20613 | 650 return -1; |
651 } | |
652 #endif | |
653 | |
35952 | 654 #ifdef __OS2__ |
31099
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
655 static int os2_open ( dvdcss_t dvdcss, char const *psz_device ) |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
656 { |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
657 char psz_dvd[] = "X:"; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
658 HFILE hfile; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
659 ULONG ulAction; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
660 ULONG rc; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
661 |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
662 psz_dvd[0] = psz_device[0]; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
663 |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
664 rc = DosOpenL( ( PSZ )psz_dvd, &hfile, &ulAction, 0, FILE_NORMAL, |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
665 OPEN_ACTION_OPEN_IF_EXISTS | OPEN_ACTION_FAIL_IF_NEW, |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
666 OPEN_ACCESS_READONLY | OPEN_SHARE_DENYNONE | OPEN_FLAGS_DASD, |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
667 NULL ); |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
668 |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
669 if( rc ) |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
670 { |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
671 print_error( dvdcss, "failed to open device" ); |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
672 return -1; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
673 } |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
674 |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
675 setmode( hfile, O_BINARY ); |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
676 |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
677 dvdcss->i_fd = dvdcss->i_read_fd = hfile; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
678 |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
679 dvdcss->i_pos = 0; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
680 |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
681 return 0; |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
682 } |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
683 #endif |
f43e87f69590
libdvdcss: OS/2 support; this merges upstream revisions 220 and 229.
diego
parents:
31098
diff
changeset
|
684 |
20613 | 685 /***************************************************************************** |
686 * Seek commands. | |
687 *****************************************************************************/ | |
688 static int libc_seek( dvdcss_t dvdcss, int i_blocks ) | |
689 { | |
690 off_t i_seek; | |
691 | |
692 if( dvdcss->i_pos == i_blocks ) | |
693 { | |
694 /* We are already in position */ | |
695 return i_blocks; | |
696 } | |
697 | |
698 i_seek = (off_t)i_blocks * (off_t)DVDCSS_BLOCK_SIZE; | |
20730
66c2f233ccff
Fix linking on Cygwin and remove nonsense lseek64 --> lseek indirection,
diego
parents:
20613
diff
changeset
|
699 i_seek = lseek( dvdcss->i_read_fd, i_seek, SEEK_SET ); |
20613 | 700 |
701 if( i_seek < 0 ) | |
702 { | |
703 print_error( dvdcss, "seek error" ); | |
704 dvdcss->i_pos = -1; | |
705 return i_seek; | |
706 } | |
707 | |
708 dvdcss->i_pos = i_seek / DVDCSS_BLOCK_SIZE; | |
709 | |
710 return dvdcss->i_pos; | |
711 } | |
712 | |
713 #if defined( WIN32 ) | |
714 static int win2k_seek( dvdcss_t dvdcss, int i_blocks ) | |
715 { | |
716 LARGE_INTEGER li_seek; | |
717 | |
718 #ifndef INVALID_SET_FILE_POINTER | |
719 # define INVALID_SET_FILE_POINTER ((DWORD)-1) | |
720 #endif | |
721 | |
722 if( dvdcss->i_pos == i_blocks ) | |
723 { | |
724 /* We are already in position */ | |
725 return i_blocks; | |
726 } | |
727 | |
728 li_seek.QuadPart = (LONGLONG)i_blocks * DVDCSS_BLOCK_SIZE; | |
729 | |
730 li_seek.LowPart = SetFilePointer( (HANDLE) dvdcss->i_fd, | |
731 li_seek.LowPart, | |
732 &li_seek.HighPart, FILE_BEGIN ); | |
733 if( (li_seek.LowPart == INVALID_SET_FILE_POINTER) | |
734 && GetLastError() != NO_ERROR) | |
735 { | |
736 dvdcss->i_pos = -1; | |
737 return -1; | |
738 } | |
739 | |
740 dvdcss->i_pos = li_seek.QuadPart / DVDCSS_BLOCK_SIZE; | |
741 | |
742 return dvdcss->i_pos; | |
743 } | |
744 | |
745 static int aspi_seek( dvdcss_t dvdcss, int i_blocks ) | |
746 { | |
747 int i_old_blocks; | |
748 char sz_buf[ DVDCSS_BLOCK_SIZE ]; | |
749 struct w32_aspidev *fd = (struct w32_aspidev *) dvdcss->i_fd; | |
750 | |
751 if( dvdcss->i_pos == i_blocks ) | |
752 { | |
753 /* We are already in position */ | |
754 return i_blocks; | |
755 } | |
756 | |
757 i_old_blocks = fd->i_blocks; | |
758 fd->i_blocks = i_blocks; | |
759 | |
760 if( aspi_read_internal( dvdcss->i_fd, sz_buf, 1 ) == -1 ) | |
761 { | |
762 fd->i_blocks = i_old_blocks; | |
763 dvdcss->i_pos = -1; | |
764 return -1; | |
765 } | |
766 | |
767 (fd->i_blocks)--; | |
768 | |
769 dvdcss->i_pos = fd->i_blocks; | |
770 | |
771 return dvdcss->i_pos; | |
772 } | |
773 #endif | |
774 | |
775 /***************************************************************************** | |
776 * Read commands. | |
777 *****************************************************************************/ | |
778 static int libc_read ( dvdcss_t dvdcss, void *p_buffer, int i_blocks ) | |
779 { | |
780 off_t i_size, i_ret; | |
781 | |
782 i_size = (off_t)i_blocks * (off_t)DVDCSS_BLOCK_SIZE; | |
783 i_ret = read( dvdcss->i_read_fd, p_buffer, i_size ); | |
784 | |
785 if( i_ret < 0 ) | |
786 { | |
787 print_error( dvdcss, "read error" ); | |
788 dvdcss->i_pos = -1; | |
789 return i_ret; | |
790 } | |
791 | |
792 /* Handle partial reads */ | |
793 if( i_ret != i_size ) | |
794 { | |
795 int i_seek; | |
796 | |
797 dvdcss->i_pos = -1; | |
798 i_seek = libc_seek( dvdcss, i_ret / DVDCSS_BLOCK_SIZE ); | |
799 if( i_seek < 0 ) | |
800 { | |
801 return i_seek; | |
802 } | |
803 | |
804 /* We have to return now so that i_pos isn't clobbered */ | |
805 return i_ret / DVDCSS_BLOCK_SIZE; | |
806 } | |
807 | |
808 dvdcss->i_pos += i_ret / DVDCSS_BLOCK_SIZE; | |
809 return i_ret / DVDCSS_BLOCK_SIZE; | |
810 } | |
811 | |
812 #if defined( WIN32 ) | |
813 static int win2k_read ( dvdcss_t dvdcss, void *p_buffer, int i_blocks ) | |
814 { | |
815 int i_bytes; | |
816 | |
817 if( !ReadFile( (HANDLE) dvdcss->i_fd, p_buffer, | |
818 i_blocks * DVDCSS_BLOCK_SIZE, | |
819 (LPDWORD)&i_bytes, NULL ) ) | |
820 { | |
821 dvdcss->i_pos = -1; | |
822 return -1; | |
823 } | |
824 | |
825 dvdcss->i_pos += i_bytes / DVDCSS_BLOCK_SIZE; | |
826 return i_bytes / DVDCSS_BLOCK_SIZE; | |
827 } | |
828 | |
829 static int aspi_read ( dvdcss_t dvdcss, void *p_buffer, int i_blocks ) | |
830 { | |
831 int i_read = aspi_read_internal( dvdcss->i_fd, p_buffer, i_blocks ); | |
832 | |
833 if( i_read < 0 ) | |
834 { | |
835 dvdcss->i_pos = -1; | |
836 return i_read; | |
837 } | |
838 | |
839 dvdcss->i_pos += i_read; | |
840 return i_read; | |
841 } | |
842 #endif | |
843 | |
844 /***************************************************************************** | |
845 * Readv commands. | |
846 *****************************************************************************/ | |
847 static int libc_readv ( dvdcss_t dvdcss, struct iovec *p_iovec, int i_blocks ) | |
848 { | |
849 #if defined( WIN32 ) | |
850 int i_index, i_len, i_total = 0; | |
851 unsigned char *p_base; | |
852 int i_bytes; | |
853 | |
854 for( i_index = i_blocks; | |
855 i_index; | |
856 i_index--, p_iovec++ ) | |
857 { | |
858 i_len = p_iovec->iov_len; | |
859 p_base = p_iovec->iov_base; | |
860 | |
861 if( i_len <= 0 ) | |
862 { | |
863 continue; | |
864 } | |
865 | |
866 i_bytes = read( dvdcss->i_fd, p_base, i_len ); | |
867 | |
868 if( i_bytes < 0 ) | |
869 { | |
870 /* One of the reads failed, too bad. | |
35952 | 871 * We won't even bother returning the reads that went OK, |
872 * and as in the POSIX spec the file position is left | |
20613 | 873 * unspecified after a failure */ |
874 dvdcss->i_pos = -1; | |
875 return -1; | |
876 } | |
877 | |
878 i_total += i_bytes; | |
879 | |
880 if( i_bytes != i_len ) | |
881 { | |
882 /* We reached the end of the file or a signal interrupted | |
883 * the read. Return a partial read. */ | |
884 int i_seek; | |
885 | |
886 dvdcss->i_pos = -1; | |
887 i_seek = libc_seek( dvdcss, i_total / DVDCSS_BLOCK_SIZE ); | |
888 if( i_seek < 0 ) | |
889 { | |
890 return i_seek; | |
891 } | |
892 | |
893 /* We have to return now so that i_pos isn't clobbered */ | |
894 return i_total / DVDCSS_BLOCK_SIZE; | |
895 } | |
896 } | |
897 | |
898 dvdcss->i_pos += i_total / DVDCSS_BLOCK_SIZE; | |
899 return i_total / DVDCSS_BLOCK_SIZE; | |
900 #else | |
901 int i_read = readv( dvdcss->i_read_fd, p_iovec, i_blocks ); | |
902 | |
903 if( i_read < 0 ) | |
904 { | |
905 dvdcss->i_pos = -1; | |
906 return i_read; | |
907 } | |
908 | |
909 dvdcss->i_pos += i_read / DVDCSS_BLOCK_SIZE; | |
910 return i_read / DVDCSS_BLOCK_SIZE; | |
911 #endif | |
912 } | |
913 | |
914 #if defined( WIN32 ) | |
915 /***************************************************************************** | |
916 * win_readv: vectored read using ReadFile for Win2K and ASPI for win9x | |
917 *****************************************************************************/ | |
918 static int win_readv ( dvdcss_t dvdcss, struct iovec *p_iovec, int i_blocks ) | |
919 { | |
920 int i_index; | |
921 int i_blocks_read, i_blocks_total = 0; | |
922 | |
923 /* Check the size of the readv temp buffer, just in case we need to | |
924 * realloc something bigger */ | |
925 if( dvdcss->i_readv_buf_size < i_blocks * DVDCSS_BLOCK_SIZE ) | |
926 { | |
927 dvdcss->i_readv_buf_size = i_blocks * DVDCSS_BLOCK_SIZE; | |
928 | |
929 if( dvdcss->p_readv_buffer ) free( dvdcss->p_readv_buffer ); | |
930 | |
931 /* Allocate a buffer which will be used as a temporary storage | |
932 * for readv */ | |
933 dvdcss->p_readv_buffer = malloc( dvdcss->i_readv_buf_size ); | |
934 if( !dvdcss->p_readv_buffer ) | |
935 { | |
936 print_error( dvdcss, " failed (readv)" ); | |
937 dvdcss->i_pos = -1; | |
938 return -1; | |
939 } | |
940 } | |
941 | |
942 for( i_index = i_blocks; i_index; i_index-- ) | |
943 { | |
944 i_blocks_total += p_iovec[i_index-1].iov_len; | |
945 } | |
946 | |
947 if( i_blocks_total <= 0 ) return 0; | |
948 | |
949 i_blocks_total /= DVDCSS_BLOCK_SIZE; | |
950 | |
951 if( WIN2K ) | |
952 { | |
953 unsigned long int i_bytes; | |
954 if( !ReadFile( (HANDLE)dvdcss->i_fd, dvdcss->p_readv_buffer, | |
955 i_blocks_total * DVDCSS_BLOCK_SIZE, &i_bytes, NULL ) ) | |
956 { | |
957 /* The read failed... too bad. | |
35952 | 958 * As in the POSIX spec the file position is left |
20613 | 959 * unspecified after a failure */ |
960 dvdcss->i_pos = -1; | |
961 return -1; | |
962 } | |
963 i_blocks_read = i_bytes / DVDCSS_BLOCK_SIZE; | |
964 } | |
965 else /* Win9x */ | |
966 { | |
967 i_blocks_read = aspi_read_internal( dvdcss->i_fd, | |
968 dvdcss->p_readv_buffer, | |
969 i_blocks_total ); | |
970 if( i_blocks_read < 0 ) | |
971 { | |
972 /* See above */ | |
973 dvdcss->i_pos = -1; | |
974 return -1; | |
975 } | |
976 } | |
977 | |
978 /* We just have to copy the content of the temp buffer into the iovecs */ | |
979 for( i_index = 0, i_blocks_total = i_blocks_read; | |
980 i_blocks_total > 0; | |
981 i_index++ ) | |
982 { | |
983 memcpy( p_iovec[i_index].iov_base, | |
984 dvdcss->p_readv_buffer + (i_blocks_read - i_blocks_total) | |
985 * DVDCSS_BLOCK_SIZE, | |
986 p_iovec[i_index].iov_len ); | |
987 /* if we read less blocks than asked, we'll just end up copying | |
988 * garbage, this isn't an issue as we return the number of | |
989 * blocks actually read */ | |
990 i_blocks_total -= ( p_iovec[i_index].iov_len / DVDCSS_BLOCK_SIZE ); | |
991 } | |
992 | |
993 dvdcss->i_pos += i_blocks_read; | |
994 return i_blocks_read; | |
995 } | |
996 | |
997 static int aspi_read_internal( int i_fd, void *p_data, int i_blocks ) | |
998 { | |
999 HANDLE hEvent; | |
35952 | 1000 struct SRB_ExecSCSICmd ssc = { 0 }; |
20613 | 1001 struct w32_aspidev *fd = (struct w32_aspidev *) i_fd; |
1002 | |
1003 /* Create the transfer completion event */ | |
1004 hEvent = CreateEvent( NULL, TRUE, FALSE, NULL ); | |
1005 if( hEvent == NULL ) | |
1006 { | |
1007 return -1; | |
1008 } | |
1009 | |
1010 ssc.SRB_Cmd = SC_EXEC_SCSI_CMD; | |
1011 ssc.SRB_Flags = SRB_DIR_IN | SRB_EVENT_NOTIFY; | |
1012 ssc.SRB_HaId = LOBYTE( fd->i_sid ); | |
1013 ssc.SRB_Target = HIBYTE( fd->i_sid ); | |
1014 ssc.SRB_SenseLen = SENSE_LEN; | |
1015 | |
1016 ssc.SRB_PostProc = (LPVOID) hEvent; | |
1017 ssc.SRB_BufPointer = p_data; | |
1018 ssc.SRB_CDBLen = 12; | |
1019 | |
1020 ssc.CDBByte[0] = 0xA8; /* RAW */ | |
1021 ssc.CDBByte[2] = (UCHAR) (fd->i_blocks >> 24); | |
1022 ssc.CDBByte[3] = (UCHAR) (fd->i_blocks >> 16) & 0xff; | |
1023 ssc.CDBByte[4] = (UCHAR) (fd->i_blocks >> 8) & 0xff; | |
1024 ssc.CDBByte[5] = (UCHAR) (fd->i_blocks) & 0xff; | |
1025 | |
35952 | 1026 /* We have to break down the reads into 64KB pieces (ASPI restriction) */ |
20613 | 1027 if( i_blocks > 32 ) |
1028 { | |
1029 ssc.SRB_BufLen = 32 * DVDCSS_BLOCK_SIZE; | |
1030 ssc.CDBByte[9] = 32; | |
1031 fd->i_blocks += 32; | |
1032 | |
1033 /* Initiate transfer */ | |
1034 ResetEvent( hEvent ); | |
1035 fd->lpSendCommand( (void*) &ssc ); | |
1036 | |
35952 | 1037 /* transfer the next 64KB (aspi_read_internal is called recursively) |
20613 | 1038 * We need to check the status of the read on return */ |
1039 if( aspi_read_internal( i_fd, | |
1040 (uint8_t*) p_data + 32 * DVDCSS_BLOCK_SIZE, | |
1041 i_blocks - 32) < 0 ) | |
1042 { | |
1043 return -1; | |
1044 } | |
1045 } | |
1046 else | |
1047 { | |
1048 /* This is the last transfer */ | |
1049 ssc.SRB_BufLen = i_blocks * DVDCSS_BLOCK_SIZE; | |
1050 ssc.CDBByte[9] = (UCHAR) i_blocks; | |
1051 fd->i_blocks += i_blocks; | |
1052 | |
1053 /* Initiate transfer */ | |
1054 ResetEvent( hEvent ); | |
1055 fd->lpSendCommand( (void*) &ssc ); | |
1056 | |
1057 } | |
1058 | |
1059 /* If the command has still not been processed, wait until it's finished */ | |
1060 if( ssc.SRB_Status == SS_PENDING ) | |
1061 { | |
1062 WaitForSingleObject( hEvent, INFINITE ); | |
1063 } | |
1064 CloseHandle( hEvent ); | |
1065 | |
1066 /* check that the transfer went as planned */ | |
1067 if( ssc.SRB_Status != SS_COMP ) | |
1068 { | |
1069 return -1; | |
1070 } | |
1071 | |
1072 return i_blocks; | |
1073 } | |
1074 #endif | |
1075 |