1 /*
2 Copyright (C) 2005, 2006, 2008, 2011-2013, 2017
3 Rocky Bernstein <rocky@gnu.org>
4
5 This program is free software: you can redistribute it and/or modify
6 it under the terms of the GNU General Public License as published by
7 the Free Software Foundation, either version 3 of the License, or
8 (at your option) any later version.
9
10 This program is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 GNU General Public License for more details.
14
15 You should have received a copy of the GNU General Public License
16 along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18 /*! device- and driver-related routines. */
19
20
21 #ifdef HAVE_CONFIG_H
22 # include "config.h"
23 # define __CDIO_CONFIG_H__ 1
24 #endif
25
26 #ifdef HAVE_STDBOOL_H
27 # include <stdbool.h>
28 #endif
29
30 #include <cdio/cdio.h>
31 #include <cdio/cd_types.h>
32 #include <cdio/logging.h>
33 #include "cdio_private.h"
34 #include <cdio/util.h>
35 #include <cdio/mmc_cmds.h>
36
37 #ifdef HAVE_STDLIB_H
38 #include <stdlib.h>
39 #endif
40
41 #ifdef HAVE_STRING_H
42 #include <string.h>
43 #endif
44
45 /* This probably will get moved to driver code, i.e _cdio_linux.c */
46 #ifdef HAVE_LINUX_MAJOR_H
47 #include <linux/major.h>
48 #endif
49 #ifdef HAVE_SYS_STAT_H
50 #include <sys/stat.h>
51 #endif
52
53 /* The last valid entry of Cdio_driver.
54 -1 or (CDIO_DRIVER_UNINIT) means uninitialzed.
55 -2 means some sort of error.
56 */
57
58 #define CDIO_DRIVER_UNINIT -1
59 int CdIo_last_driver = CDIO_DRIVER_UNINIT;
60
61 #ifdef HAVE_AIX_CDROM
62 const driver_id_t cdio_os_driver = DRIVER_AIX;
63 #elif defined(HAVE_FREEBSD_CDROM)
64 const driver_id_t cdio_os_driver = DRIVER_FREEBSD;
65 #elif defined(HAVE_LINUX_CDROM)
66 const driver_id_t cdio_os_driver = DRIVER_LINUX;
67 #elif defined(HAVE_NETBSD_CDROM)
68 const driver_id_t cdio_os_driver = DRIVER_NETBSD;
69 #elif defined(HAVE_DARWIN_CDROM)
70 const driver_id_t cdio_os_driver = DRIVER_OSX;
71 #elif defined(HAVE_SOLARIS_CDROM)
72 const driver_id_t cdio_os_driver = DRIVER_SOLARIS;
73 #elif defined(HAVE_WIN32_CDROM)
74 const driver_id_t cdio_os_driver = DRIVER_WIN32;
75 #else
76 const driver_id_t cdio_os_driver = DRIVER_UNKNOWN;
77 #endif
78
79 /** The below variables are trickery to force enum symbol values to be
80 recorded in debug symbol tables. They are used to allow one to refer
81 to the enumeration value names in the typedefs above in a debugger
82 and debugger expressions.
83 */
84 cdio_drive_cap_misc_t debug_cdio_drive_cap_misc;
85 cdio_drive_cap_read_t debug_cdio_drive_cap_read_t;
86 cdio_drive_cap_write_t debug_drive_cap_write_t;
87 cdio_mmc_hw_len_t debug_cdio_mmc_hw_len;
88 cdio_src_category_mask_t debug_cdio_src_category_mask;
89
90 static bool
cdio_have_false(void)91 cdio_have_false(void)
92 {
93 return false;
94 }
95
96 /* The below array gives all drivers that can possibly appear.
97 on a particular host. */
98
99 CdIo_driver_t CdIo_all_drivers[] = {
100 {DRIVER_UNKNOWN,
101 0,
102 "Unknown",
103 "No driver",
104 &cdio_have_false,
105 NULL,
106 NULL,
107 NULL,
108 NULL,
109 NULL,
110 NULL
111 },
112
113 {DRIVER_AIX,
114 CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK,
115 "AIX",
116 "AIX SCSI driver",
117 &cdio_have_aix,
118 &cdio_open_aix,
119 &cdio_open_am_aix,
120 &cdio_get_default_device_aix,
121 &cdio_is_device_generic,
122 &cdio_get_devices_aix,
123 NULL
124 },
125
126 {DRIVER_FREEBSD,
127 CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK,
128 "FreeBSD",
129 "FreeBSD driver",
130 &cdio_have_freebsd,
131 &cdio_open_freebsd,
132 &cdio_open_am_freebsd,
133 &cdio_get_default_device_freebsd,
134 &cdio_is_device_generic,
135 &cdio_get_devices_freebsd,
136 &close_tray_freebsd
137 },
138
139 {DRIVER_NETBSD,
140 CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK,
141 "NetBSD",
142 "NetBSD driver",
143 &cdio_have_netbsd,
144 &cdio_open_netbsd,
145 &cdio_open_am_netbsd,
146 &cdio_get_default_device_netbsd,
147 &cdio_is_device_generic,
148 &cdio_get_devices_netbsd,
149 &close_tray_netbsd
150 },
151
152 {DRIVER_LINUX,
153 CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK,
154 "GNU/Linux",
155 "GNU/Linux ioctl and MMC driver",
156 &cdio_have_linux,
157 &cdio_open_linux,
158 &cdio_open_am_linux,
159 &cdio_get_default_device_linux,
160 &cdio_is_device_generic,
161 &cdio_get_devices_linux,
162 &close_tray_linux
163 },
164
165 {DRIVER_SOLARIS,
166 CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK,
167 "Solaris",
168 "Solaris ATAPI and SCSI driver",
169 &cdio_have_solaris,
170 &cdio_open_solaris,
171 &cdio_open_am_solaris,
172 &cdio_get_default_device_solaris,
173 &cdio_is_device_generic,
174 &cdio_get_devices_solaris,
175 &close_tray_solaris
176 },
177
178 {DRIVER_OSX,
179 CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK,
180 "macOS",
181 "Apple macOS driver",
182 &cdio_have_osx,
183 &cdio_open_osx,
184 &cdio_open_am_osx,
185 &cdio_get_default_device_osx,
186 &cdio_is_device_generic,
187 &cdio_get_devices_osx,
188 &close_tray_osx
189 },
190
191 {DRIVER_WIN32,
192 CDIO_SRC_IS_DEVICE_MASK|CDIO_SRC_IS_NATIVE_MASK|CDIO_SRC_IS_SCSI_MASK,
193 "WIN32",
194 "MS Windows ASPI and ioctl driver",
195 &cdio_have_win32,
196 &cdio_open_win32,
197 &cdio_open_am_win32,
198 &cdio_get_default_device_win32,
199 &cdio_is_device_win32,
200 &cdio_get_devices_win32,
201 &close_tray_win32
202 },
203
204 {DRIVER_CDRDAO,
205 CDIO_SRC_IS_DISK_IMAGE_MASK,
206 "CDRDAO",
207 "cdrdao (TOC) disk image driver",
208 &cdio_have_cdrdao,
209 &cdio_open_cdrdao,
210 &cdio_open_am_cdrdao,
211 &cdio_get_default_device_cdrdao,
212 NULL,
213 &cdio_get_devices_cdrdao,
214 NULL
215 },
216
217 {DRIVER_BINCUE,
218 CDIO_SRC_IS_DISK_IMAGE_MASK,
219 "BIN/CUE",
220 "bin/cuesheet disk image driver",
221 &cdio_have_bincue,
222 &cdio_open_bincue,
223 &cdio_open_am_bincue,
224 &cdio_get_default_device_bincue,
225 NULL,
226 &cdio_get_devices_bincue,
227 NULL
228 },
229
230 {DRIVER_NRG,
231 CDIO_SRC_IS_DISK_IMAGE_MASK,
232 "NRG",
233 "Nero NRG disk image driver",
234 &cdio_have_nrg,
235 &cdio_open_nrg,
236 &cdio_open_am_nrg,
237 &cdio_get_default_device_nrg,
238 NULL,
239 &cdio_get_devices_nrg,
240 NULL
241 }
242
243 };
244
245 /* The below array gives of the drivers that are currently available for
246 on a particular host. */
247
248 CdIo_driver_t CdIo_driver[sizeof(CdIo_all_drivers)/sizeof(CdIo_all_drivers[0])-1] = {
249 {0, 0, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL} };
250
251 const driver_id_t cdio_drivers[] = {
252 DRIVER_AIX,
253 DRIVER_FREEBSD,
254 DRIVER_NETBSD,
255 DRIVER_LINUX,
256 DRIVER_SOLARIS,
257 DRIVER_OSX,
258 DRIVER_WIN32,
259 DRIVER_CDRDAO,
260 DRIVER_BINCUE,
261 DRIVER_NRG,
262 DRIVER_UNKNOWN
263 };
264
265 const driver_id_t cdio_device_drivers[] = {
266 DRIVER_AIX,
267 DRIVER_FREEBSD,
268 DRIVER_NETBSD,
269 DRIVER_LINUX,
270 DRIVER_SOLARIS,
271 DRIVER_OSX,
272 DRIVER_WIN32,
273 DRIVER_UNKNOWN
274 };
275
276 const char *
cdio_driver_errmsg(driver_return_code_t drc)277 cdio_driver_errmsg(driver_return_code_t drc)
278 {
279 switch(drc) {
280 case DRIVER_OP_SUCCESS:
281 return "driver operation was successful";
282 case DRIVER_OP_ERROR:
283 return "driver I/O error";
284 case DRIVER_OP_UNSUPPORTED:
285 return "driver operatation not supported";
286 case DRIVER_OP_UNINIT:
287 return "driver not initialized";
288 case DRIVER_OP_NOT_PERMITTED:
289 return "driver operatation not permitted";
290 case DRIVER_OP_BAD_PARAMETER:
291 return "bad parameter passed";
292 case DRIVER_OP_BAD_POINTER:
293 return "bad pointer to memory area";
294 case DRIVER_OP_NO_DRIVER:
295 return "driver not available";
296 default:
297 return "unknown or bad driver return status";
298 }
299 }
300
301 static CdIo *
scan_for_driver(const driver_id_t drivers[],const char * psz_source,const char * access_mode)302 scan_for_driver(const driver_id_t drivers[],
303 const char *psz_source, const char *access_mode)
304 {
305 const driver_id_t *p_driver_id;
306
307 for (p_driver_id=drivers; *p_driver_id!=DRIVER_UNKNOWN; p_driver_id++) {
308 cdio_debug("Trying driver %s",
309 cdio_get_driver_name_from_id(*p_driver_id));
310 if ((*CdIo_all_drivers[*p_driver_id].have_driver)()) {
311 CdIo *ret=
312 (*CdIo_all_drivers[*p_driver_id].driver_open_am)(psz_source, access_mode);
313 if (ret != NULL) {
314 ret->driver_id = *p_driver_id;
315 cdio_info("found driver %s", cdio_get_driver_name_from_id(*p_driver_id));
316 return ret;
317 }
318 }
319 }
320 return NULL;
321 }
322
323 const char *
cdio_driver_describe(driver_id_t driver_id)324 cdio_driver_describe(driver_id_t driver_id)
325 {
326 return CdIo_all_drivers[driver_id].describe;
327 }
328
329 /*!
330 Initialize CD Reading and control routines. Should be called first.
331 May be implicitly called by other routines if not called first.
332 */
333 bool
cdio_init(void)334 cdio_init(void)
335 {
336
337 CdIo_driver_t *all_dp;
338 CdIo_driver_t *dp = CdIo_driver;
339 const driver_id_t *p_driver_id;
340
341 if (CdIo_last_driver != CDIO_DRIVER_UNINIT) {
342 cdio_warn ("Init routine called more than once.");
343 return false;
344 }
345
346 for (p_driver_id=cdio_drivers; *p_driver_id!=DRIVER_UNKNOWN; p_driver_id++) {
347 all_dp = &CdIo_all_drivers[*p_driver_id];
348 if ((*CdIo_all_drivers[*p_driver_id].have_driver)()) {
349 *dp++ = *all_dp;
350 CdIo_last_driver++;
351 }
352 }
353
354 return true;
355 }
356
357 /*!
358 Free any resources associated with cdio.
359 */
360 void
cdio_destroy(CdIo_t * p_cdio)361 cdio_destroy (CdIo_t *p_cdio)
362 {
363 CdIo_last_driver = CDIO_DRIVER_UNINIT;
364 if (p_cdio == NULL) return;
365
366 if (p_cdio->op.free != NULL && p_cdio->env)
367 p_cdio->op.free (p_cdio->env);
368 p_cdio->env = NULL;
369 free (p_cdio);
370 }
371
372 /*!
373 Close media tray in CD drive if there is a routine to do so.
374
375 @param psz_drive the name of CD-ROM to be closed. If NULL, we will
376 use the default device.
377 @param p_driver_id is the driver to be used or that got used if
378 it was DRIVER_UNKNOWN or DRIVER_DEVICE; If this is NULL, we won't
379 report back the driver used.
380 */
381 driver_return_code_t
cdio_close_tray(const char * psz_orig_drive,driver_id_t * p_driver_id)382 cdio_close_tray (const char *psz_orig_drive, /*in/out*/ driver_id_t
383 *p_driver_id)
384 {
385 driver_id_t temp_driver_id = DRIVER_DEVICE;
386 char *psz_drive;
387 driver_return_code_t drc;
388
389 if (!p_driver_id) p_driver_id = &temp_driver_id;
390
391 if (!psz_orig_drive || !*psz_orig_drive)
392 psz_drive = cdio_get_default_device_driver(p_driver_id);
393 else
394 psz_drive = strdup(psz_orig_drive);
395
396 if (DRIVER_UNKNOWN == *p_driver_id || DRIVER_DEVICE == *p_driver_id) {
397 const driver_id_t *_p_driver_id =
398 (DRIVER_DEVICE == *p_driver_id)?cdio_device_drivers:cdio_drivers;
399 p_driver_id = (driver_id_t *)_p_driver_id;
400
401 /* Scan for driver */
402 for ( ; *p_driver_id!=DRIVER_UNKNOWN; p_driver_id++) {
403 if ( (*CdIo_all_drivers[*p_driver_id].have_driver)() &&
404 *CdIo_all_drivers[*p_driver_id].close_tray ) {
405 drc = (*CdIo_all_drivers[*p_driver_id].close_tray)(psz_drive);
406 free(psz_drive);
407 return drc;
408 }
409 }
410 free(psz_drive);
411 return DRIVER_OP_UNSUPPORTED;
412 }
413
414 /* The driver id was specified. Use that. */
415 if ( (*CdIo_all_drivers[*p_driver_id].have_driver)() &&
416 *CdIo_all_drivers[*p_driver_id].close_tray ) {
417 drc = (*CdIo_all_drivers[*p_driver_id].close_tray)(psz_drive);
418 free(psz_drive);
419 return drc;
420 }
421
422 free(psz_drive);
423 return DRIVER_OP_UNSUPPORTED;
424 }
425
426 /*!
427 Eject media in CD drive if there is a routine to do so.
428
429 @param p_cdio the CD object to be acted upon.
430 If the CD is ejected *p_cdio is freed and p_cdio set to NULL.
431 */
432 driver_return_code_t
cdio_eject_media(CdIo_t ** pp_cdio)433 cdio_eject_media (CdIo_t **pp_cdio)
434 {
435 if ((pp_cdio == NULL) || (*pp_cdio == NULL)) return DRIVER_OP_UNINIT;
436
437 if ((*pp_cdio)->op.eject_media) {
438 int ret = (*pp_cdio)->op.eject_media ((*pp_cdio)->env);
439 if (0 == ret) {
440 cdio_destroy(*pp_cdio);
441 *pp_cdio = NULL;
442 }
443 return ret;
444 } else {
445 cdio_destroy(*pp_cdio);
446 *pp_cdio = NULL;
447 return DRIVER_OP_UNSUPPORTED;
448 }
449 }
450
451 /*!
452 Eject media in CD drive if there is a routine to do so. If you want
453 to scan for any CD-ROM and eject that, pass NULL for psz_drive.
454
455 @param psz_drive the CD object to be acted upon.
456 If NULL is given as the drive, we'll use the default driver device.
457 */
458 driver_return_code_t
cdio_eject_media_drive(const char * psz_drive)459 cdio_eject_media_drive (const char *psz_drive)
460 {
461 CdIo_t *p_cdio = cdio_open (psz_drive, DRIVER_DEVICE);
462 if (p_cdio) {
463 driver_return_code_t rc;
464 rc = cdio_eject_media(&p_cdio);
465 cdio_destroy(p_cdio);
466 return rc;
467 } else {
468 return DRIVER_OP_UNINIT;
469 }
470 }
471
472 /*!
473 Free device list returned by cdio_get_devices or
474 cdio_get_devices_with_cap.
475 */
476 void
cdio_free_device_list(char * ppsz_device_list[])477 cdio_free_device_list (char * ppsz_device_list[])
478 {
479 char **ppsz_device_list_save=ppsz_device_list;
480 if (!ppsz_device_list) return;
481 for ( ; NULL != *ppsz_device_list ; ppsz_device_list++ ) {
482 free(*ppsz_device_list);
483 *ppsz_device_list = NULL;
484 }
485 CDIO_FREE_IF_NOT_NULL(ppsz_device_list_save);
486 }
487
488
489 /*!
490 Return a string containing the default CD device if none is specified.
491 if p_cdio is NULL (we haven't initialized a specific device driver),
492 then find a suitable one and return the default device for that.
493
494 NULL is returned if we couldn't get a default device.
495 */
496 char *
cdio_get_default_device(const CdIo_t * p_cdio)497 cdio_get_default_device (const CdIo_t *p_cdio)
498 {
499 if (p_cdio == NULL) {
500 const driver_id_t *p_driver_id;
501 /* Scan for driver */
502 for (p_driver_id=cdio_drivers; *p_driver_id!=DRIVER_UNKNOWN; p_driver_id++) {
503 if ( (*CdIo_all_drivers[*p_driver_id].have_driver)() &&
504 *CdIo_all_drivers[*p_driver_id].get_default_device ) {
505 return (*CdIo_all_drivers[*p_driver_id].get_default_device)();
506 }
507 }
508 return NULL;
509 }
510
511 if (p_cdio->op.get_default_device) {
512 return p_cdio->op.get_default_device ();
513 } else {
514 return NULL;
515 }
516 }
517
518 /*!
519 Return a string containing the default CD device if none is specified.
520 if p_driver_id is DRIVER_UNKNOWN or DRIVER_DEVICE
521 then find a suitable one set the default device for that.
522
523 NULL is returned if we couldn't get a default device.
524 */
525 char *
cdio_get_default_device_driver(driver_id_t * p_driver_id)526 cdio_get_default_device_driver (/*in/out*/ driver_id_t *p_driver_id)
527 {
528 if (DRIVER_UNKNOWN == *p_driver_id || DRIVER_DEVICE == *p_driver_id) {
529 const driver_id_t *p_driver_id_try =
530 (DRIVER_DEVICE == *p_driver_id)?cdio_device_drivers:cdio_drivers;
531
532 /* Scan for driver */
533 for ( ; *p_driver_id_try!=DRIVER_UNKNOWN; p_driver_id_try++) {
534 if ( (*CdIo_all_drivers[*p_driver_id_try].have_driver)() &&
535 *CdIo_all_drivers[*p_driver_id_try].get_default_device ) {
536 *p_driver_id = *p_driver_id_try;
537 return (*CdIo_all_drivers[*p_driver_id].get_default_device)();
538 }
539 }
540 return NULL;
541 }
542
543 /* The driver id was specified. Use that. */
544 if ( (*CdIo_all_drivers[*p_driver_id].have_driver)() &&
545 *CdIo_all_drivers[*p_driver_id].get_default_device ) {
546 return (*CdIo_all_drivers[*p_driver_id].get_default_device)();
547 }
548 return NULL;
549 }
550
551 /*!Return an array of device names. If you want a specific
552 devices, dor a driver give that device, if you want hardware
553 devices, give DRIVER_DEVICE and if you want all possible devices,
554 image drivers and hardware drivers give DRIVER_UNKNOWN.
555
556 NULL is returned if we couldn't return a list of devices.
557 */
558 char **
cdio_get_devices(driver_id_t driver_id)559 cdio_get_devices (driver_id_t driver_id)
560 {
561 /* Probably could get away with &driver_id below. */
562 driver_id_t driver_id_temp = driver_id;
563 return cdio_get_devices_ret (&driver_id_temp);
564 }
565
566 char **
cdio_get_devices_ret(driver_id_t * p_driver_id)567 cdio_get_devices_ret (/*in/out*/ driver_id_t *p_driver_id)
568 {
569 CdIo_t *p_cdio;
570
571 switch (*p_driver_id) {
572 /* FIXME: spit out unknown to give image drivers as well. */
573 case DRIVER_DEVICE:
574 p_cdio = scan_for_driver(cdio_device_drivers, NULL, NULL);
575 *p_driver_id = cdio_get_driver_id(p_cdio);
576 break;
577 case DRIVER_UNKNOWN:
578 p_cdio = scan_for_driver(cdio_drivers, NULL, NULL);
579 *p_driver_id = cdio_get_driver_id(p_cdio);
580 break;
581 default:
582 return (*CdIo_all_drivers[*p_driver_id].get_devices)();
583 }
584
585 if (p_cdio == NULL) return NULL;
586 if (p_cdio->op.get_devices) {
587 char **devices = p_cdio->op.get_devices ();
588 cdio_destroy(p_cdio);
589 return devices;
590 } else {
591 return NULL;
592 }
593 }
594
595 /*!
596 Return an array of device names in search_devices that have at
597 least the capabilities listed by cap. If search_devices is NULL,
598 then we'll search all possible CD drives.
599
600 If "any" is set false then every capability listed in the extended
601 portion of capabilities (i.e. not the basic filesystem) must be
602 satisified. If "any" is set true, then if any of the capabilities
603 matches, we call that a success.
604
605 To find a CD-drive of any type, use the mask CDIO_FS_MATCH_ALL.
606
607 NULL is returned if we couldn't get a default device.
608 It is also possible to return a non NULL but after dereferencing the
609 the value is NULL. This also means nothing was found.
610 */
611 char **
cdio_get_devices_with_cap(char * search_devices[],cdio_fs_anal_t capabilities,bool any)612 cdio_get_devices_with_cap (/*in*/ char* search_devices[],
613 cdio_fs_anal_t capabilities, bool any)
614 {
615 driver_id_t p_driver_id;
616 return cdio_get_devices_with_cap_ret (search_devices, capabilities, any,
617 &p_driver_id);
618 }
619
620 char **
cdio_get_devices_with_cap_ret(char * search_devices[],cdio_fs_anal_t need_cap,bool b_any,driver_id_t * p_driver_id)621 cdio_get_devices_with_cap_ret (/*in*/ char* search_devices[],
622 cdio_fs_anal_t need_cap, bool b_any,
623 /*out*/ driver_id_t *p_driver_id)
624 {
625 char **ppsz_drives=search_devices;
626 char **ppsz_drives_ret=NULL;
627 unsigned int i_drives=0;
628 bool b_free_ppsz_drives = false;
629
630 *p_driver_id = DRIVER_DEVICE;
631
632 if (!ppsz_drives) {
633 ppsz_drives=cdio_get_devices_ret(p_driver_id);
634 b_free_ppsz_drives = true;
635 }
636
637 if (!ppsz_drives) return NULL;
638
639 if (need_cap == CDIO_FS_MATCH_ALL) {
640 /* Duplicate drives into drives_ret. */
641 char **d = ppsz_drives;
642
643 for( ; *d != NULL; d++ ) {
644 cdio_add_device_list(&ppsz_drives_ret, *d, &i_drives);
645 }
646 } else {
647 const cdio_fs_anal_t need_fs = CDIO_FSTYPE(need_cap);
648 char **d = ppsz_drives;
649
650 for( ; *d != NULL; d++ ) {
651 CdIo_t *p_cdio = cdio_open(*d, *p_driver_id);
652
653 if (NULL != p_cdio) {
654 track_t i_first_track = cdio_get_first_track_num(p_cdio);
655 cdio_iso_analysis_t cdio_iso_analysis;
656
657 if (CDIO_INVALID_TRACK != i_first_track) {
658 const cdio_fs_anal_t got_cap =
659 cdio_guess_cd_type(p_cdio, 0, i_first_track, &cdio_iso_analysis);
660
661 /* Match on filesystem. Here either we don't know what the
662 filesystem is - automatic match, or we no that the file
663 system is in the set of those specified.
664 We refine the logic further after this initial test. */
665 if ( CDIO_FS_UNKNOWN == need_fs || 0 == need_fs
666 || (CDIO_FSTYPE(got_cap) == need_fs) ) {
667 /* Match on analysis type. If we haven't set any
668 analysis type, then an automatic match. Otherwise
669 a match is determined by whether we need all
670 analysis types or any of them. */
671 const cdio_fs_anal_t need_anal = need_cap & ~CDIO_FS_MASK;
672 const cdio_fs_anal_t got_anal = got_cap & ~CDIO_FS_MASK;
673 const bool b_match = !need_anal
674 || (b_any
675 ? (got_anal & need_anal) != 0
676 : (got_anal & need_anal) == need_anal);
677 if (b_match)
678 cdio_add_device_list(&ppsz_drives_ret, *d, &i_drives);
679 }
680 }
681
682 cdio_destroy(p_cdio);
683 }
684 }
685 }
686 cdio_add_device_list(&ppsz_drives_ret, NULL, &i_drives);
687 if (b_free_ppsz_drives) {
688 cdio_free_device_list(ppsz_drives);
689 }
690 return ppsz_drives_ret;
691 }
692
693 /*!
694 Return the the kind of drive capabilities of device.
695
696 Note: string is malloc'd so caller should free() then returned
697 string when done with it.
698
699 */
700 void
cdio_get_drive_cap(const CdIo_t * p_cdio,cdio_drive_read_cap_t * p_read_cap,cdio_drive_write_cap_t * p_write_cap,cdio_drive_misc_cap_t * p_misc_cap)701 cdio_get_drive_cap (const CdIo_t *p_cdio,
702 cdio_drive_read_cap_t *p_read_cap,
703 cdio_drive_write_cap_t *p_write_cap,
704 cdio_drive_misc_cap_t *p_misc_cap)
705 {
706 /* This seems like a safe bet. */
707 *p_read_cap = CDIO_DRIVE_CAP_UNKNOWN;
708 *p_write_cap = CDIO_DRIVE_CAP_UNKNOWN;
709 *p_misc_cap = CDIO_DRIVE_CAP_UNKNOWN;
710
711 if (p_cdio && p_cdio->op.get_drive_cap) {
712 p_cdio->op.get_drive_cap(p_cdio->env, p_read_cap, p_write_cap, p_misc_cap);
713 }
714 }
715
716 /*!
717 Return the the kind of drive capabilities of device.
718
719 Note: string is malloc'd so caller should free() then returned
720 string when done with it.
721
722 */
723 void
cdio_get_drive_cap_dev(const char * device,cdio_drive_read_cap_t * p_read_cap,cdio_drive_write_cap_t * p_write_cap,cdio_drive_misc_cap_t * p_misc_cap)724 cdio_get_drive_cap_dev (const char *device,
725 cdio_drive_read_cap_t *p_read_cap,
726 cdio_drive_write_cap_t *p_write_cap,
727 cdio_drive_misc_cap_t *p_misc_cap)
728 {
729 /* This seems like a safe bet. */
730 CdIo_t *cdio=scan_for_driver(cdio_drivers, device, NULL);
731 if (cdio) {
732 cdio_get_drive_cap(cdio, p_read_cap, p_write_cap, p_misc_cap);
733 cdio_destroy(cdio);
734 } else {
735 *p_read_cap = CDIO_DRIVE_CAP_UNKNOWN;
736 *p_write_cap = CDIO_DRIVE_CAP_UNKNOWN;
737 *p_misc_cap = CDIO_DRIVE_CAP_UNKNOWN;
738 }
739 }
740
741
742 /*!
743 Return a string containing the name of the driver in use.
744 if CdIo is NULL (we haven't initialized a specific device driver),
745 then return NULL.
746 */
747 const char *
cdio_get_driver_name(const CdIo_t * p_cdio)748 cdio_get_driver_name (const CdIo_t *p_cdio)
749 {
750 if (NULL==p_cdio) return NULL;
751 return cdio_get_driver_name_from_id(p_cdio->driver_id);
752 }
753
754 /*!
755 Return a string containing the name of the driver in use from the driver_id.
756 if CdIo is NULL (we haven't initialized a specific device driver),
757 then return NULL.
758 */
759 const char *
cdio_get_driver_name_from_id(driver_id_t driver_id)760 cdio_get_driver_name_from_id (driver_id_t driver_id)
761 {
762 return CdIo_all_drivers[driver_id].name;
763 }
764
765 /*!
766 Return the driver id.
767 if CdIo is NULL (we haven't initialized a specific device driver),
768 then return DRIVER_UNKNOWN.
769 */
770 driver_id_t
cdio_get_driver_id(const CdIo_t * p_cdio)771 cdio_get_driver_id (const CdIo_t *p_cdio)
772 {
773 if (!p_cdio) return DRIVER_UNKNOWN;
774 return p_cdio->driver_id;
775 }
776
777 /*!
778 Return a string containing the name of the driver in use.
779 if CdIo is NULL (we haven't initialized a specific device driver),
780 then return NULL.
781 */
782 bool
cdio_get_hwinfo(const CdIo_t * p_cdio,cdio_hwinfo_t * hw_info)783 cdio_get_hwinfo (const CdIo_t *p_cdio, cdio_hwinfo_t *hw_info)
784 {
785 if (!p_cdio) return false;
786 if (p_cdio->op.get_hwinfo) {
787 return p_cdio->op.get_hwinfo (p_cdio, hw_info);
788 } else {
789 /* Perhaps driver forgot to initialize. We are no worse off Using
790 mmc than returning false here. */
791 return mmc_get_hwinfo(p_cdio, hw_info);
792 }
793 }
794
795 /*!
796 Return the session number of the last on the CD.
797
798 @param p_cdio the CD object to be acted upon.
799 @param i_last_session pointer to the session number to be returned.
800 */
cdio_get_last_session(CdIo_t * p_cdio,lsn_t * i_last_session)801 driver_return_code_t cdio_get_last_session (CdIo_t *p_cdio,
802 /*out*/ lsn_t *i_last_session)
803 {
804 if (!p_cdio) return DRIVER_OP_UNINIT;
805 if (p_cdio->op.get_last_session)
806 return p_cdio->op.get_last_session(p_cdio->env, i_last_session);
807 return DRIVER_OP_UNSUPPORTED;
808 }
809
810 /*!
811 Find out if media has changed since the last call.
812 @param p_cdio the CD object to be acted upon.
813 @return 1 if media has changed since last call, 0 if not. Error
814 return codes are the same as driver_return_code_t
815 */
816 int
cdio_get_media_changed(CdIo_t * p_cdio)817 cdio_get_media_changed(CdIo_t *p_cdio)
818 {
819 if (!p_cdio) return DRIVER_OP_UNINIT;
820 if (p_cdio->op.get_media_changed)
821 return p_cdio->op.get_media_changed(p_cdio->env);
822 return DRIVER_OP_UNSUPPORTED;
823 }
824
825 bool_3way_t
cdio_have_atapi(CdIo_t * p_cdio)826 cdio_have_atapi(CdIo_t *p_cdio)
827 {
828 bool_3way_t i_status;
829
830 if (!p_cdio) return nope;
831 i_status = mmc_have_interface(p_cdio, CDIO_MMC_FEATURE_INTERFACE_ATAPI);
832 if (dunno != i_status) return i_status;
833
834 {
835 /* cdparanoia seems to think that if we have a mode sense command
836 we have an atapi drive or is atapi compatible.
837 */
838 uint8_t buf[22];
839 if (DRIVER_OP_SUCCESS == mmc_mode_sense(p_cdio, buf, sizeof(buf),
840 CDIO_MMC_CAPABILITIES_PAGE) ) {
841 uint8_t *b = buf;
842 b+=b[3]+4;
843 if( CDIO_MMC_CAPABILITIES_PAGE == (b[0]&0x3F) ) {
844 /* MMC style drive! */
845 return yep;
846 }
847 }
848 }
849
850 /* Put these in the various drivers? If we get more, yes!
851 */
852 #ifdef HAVE_LINUX_MAJOR_H
853 {
854 /* This too is from cdparanoia. */
855 struct stat st;
856 generic_img_private_t *p_env = p_cdio->env;
857 if ( 0 == lstat(p_env->source_name, &st) ) {
858 if (S_ISCHR(st.st_mode) || S_ISBLK(st.st_mode)) {
859 int drive_type=(int)(st.st_rdev>>8);
860 switch (drive_type) {
861 case IDE0_MAJOR:
862 case IDE1_MAJOR:
863 case IDE2_MAJOR:
864 case IDE3_MAJOR:
865 /* Yay, ATAPI... */
866 return yep;
867 break;
868 case CDU31A_CDROM_MAJOR:
869 case CDU535_CDROM_MAJOR:
870 case MATSUSHITA_CDROM_MAJOR:
871 case MATSUSHITA_CDROM2_MAJOR:
872 case MATSUSHITA_CDROM3_MAJOR:
873 case MATSUSHITA_CDROM4_MAJOR:
874 case SANYO_CDROM_MAJOR:
875 case MITSUMI_CDROM_MAJOR:
876 case MITSUMI_X_CDROM_MAJOR:
877 case OPTICS_CDROM_MAJOR:
878 case AZTECH_CDROM_MAJOR:
879 case GOLDSTAR_CDROM_MAJOR:
880 case CM206_CDROM_MAJOR:
881 case SCSI_CDROM_MAJOR:
882 case SCSI_GENERIC_MAJOR:
883 return nope;
884 break;
885 default:
886 return dunno;
887 }
888 }
889 }
890 }
891 #endif /*HAVE_LINUX_MAJOR_H*/
892 return dunno;
893 }
894
895 bool
cdio_have_driver(driver_id_t driver_id)896 cdio_have_driver(driver_id_t driver_id)
897 {
898 if (driver_id >= sizeof(CdIo_all_drivers)/sizeof(CdIo_all_drivers[0]))
899 return false;
900 return (*CdIo_all_drivers[driver_id].have_driver)();
901 }
902
903 bool
cdio_is_device(const char * psz_source,driver_id_t driver_id)904 cdio_is_device(const char *psz_source, driver_id_t driver_id)
905 {
906 if (DRIVER_UNKNOWN == driver_id || DRIVER_DEVICE == driver_id) {
907 const driver_id_t *p_driver_id = (DRIVER_DEVICE == driver_id)?cdio_device_drivers:cdio_drivers;
908
909 /* Scan for driver */
910 for ( ; *p_driver_id!=DRIVER_UNKNOWN; p_driver_id++) {
911 if ( (*CdIo_all_drivers[*p_driver_id].have_driver)() &&
912 CdIo_all_drivers[*p_driver_id].is_device ) {
913 return (*CdIo_all_drivers[*p_driver_id].is_device)(psz_source);
914 }
915 }
916 }
917 if (CdIo_all_drivers[driver_id].is_device == NULL) return false;
918 return (*CdIo_all_drivers[driver_id].is_device)(psz_source);
919 }
920
921
922 /*! Sets up to read from place specified by source_name and
923 driver_id. This should be called before using any other routine,
924 except cdio_init. This will call cdio_init, if that hasn't been
925 done previously.
926
927 NULL is returned on error.
928 */
929 CdIo_t *
cdio_open(const char * orig_source_name,driver_id_t driver_id)930 cdio_open (const char *orig_source_name, driver_id_t driver_id)
931 {
932 return cdio_open_am(orig_source_name, driver_id, NULL);
933 }
934
935 /*! Sets up to read from place specified by source_name and
936 driver_id. This should be called before using any other routine,
937 except cdio_init. This will call cdio_init, if that hasn't been
938 done previously.
939
940 NULL is returned on error.
941 */
942 CdIo_t *
cdio_open_am(const char * psz_orig_source,driver_id_t driver_id,const char * psz_access_mode)943 cdio_open_am (const char *psz_orig_source, driver_id_t driver_id,
944 const char *psz_access_mode)
945 {
946 char *psz_source;
947
948 if (CdIo_last_driver == -1) cdio_init();
949
950 if (!psz_orig_source || !*psz_orig_source)
951 psz_source = cdio_get_default_device(NULL);
952 else
953 psz_source = strdup(psz_orig_source);
954
955 switch (driver_id) {
956 case DRIVER_UNKNOWN:
957 {
958 CdIo_t *p_cdio=scan_for_driver(cdio_drivers,
959 psz_source, psz_access_mode);
960 free(psz_source);
961 return p_cdio;
962 }
963 case DRIVER_DEVICE:
964 {
965 /* Scan for a driver. */
966 CdIo_t *ret = cdio_open_am_cd(psz_source, psz_access_mode);
967 free(psz_source);
968 return ret;
969 }
970 break;
971 case DRIVER_AIX:
972 case DRIVER_FREEBSD:
973 case DRIVER_LINUX:
974 case DRIVER_NETBSD:
975 case DRIVER_SOLARIS:
976 case DRIVER_WIN32:
977 case DRIVER_OSX:
978 case DRIVER_NRG:
979 case DRIVER_BINCUE:
980 case DRIVER_CDRDAO:
981 if ((*CdIo_all_drivers[driver_id].have_driver)()) {
982 CdIo_t *ret =
983 (*CdIo_all_drivers[driver_id].driver_open_am)(psz_source,
984 psz_access_mode);
985 if (ret) ret->driver_id = driver_id;
986 free(psz_source);
987 return ret;
988 }
989 }
990
991 free(psz_source);
992 return NULL;
993 }
994
995
996 /*!
997 Set up CD-ROM for reading. The device_name is
998 the some sort of device name.
999
1000 @return the cdio object for subsequent operations.
1001 NULL on error or there is no driver for a some sort of hardware CD-ROM.
1002 */
1003 CdIo_t *
cdio_open_cd(const char * psz_source)1004 cdio_open_cd (const char *psz_source)
1005 {
1006 return cdio_open_am_cd(psz_source, NULL);
1007 }
1008
1009 /*!
1010 Set up CD-ROM for reading. The device_name is
1011 the some sort of device name.
1012
1013 @return the cdio object for subsequent operations.
1014 NULL on error or there is no driver for a some sort of hardware CD-ROM.
1015 */
1016 /* In the future we'll have more complicated code to allow selection
1017 of an I/O routine as well as code to find an appropriate default
1018 routine among the "registered" routines. Possibly classes too
1019 disk-based, SCSI-based, native-based, vendor (e.g. Sony, or
1020 Plextor) based
1021
1022 For now though, we'll start more simply...
1023 */
1024 CdIo_t *
cdio_open_am_cd(const char * psz_source,const char * psz_access_mode)1025 cdio_open_am_cd (const char *psz_source, const char *psz_access_mode)
1026 {
1027 if (CdIo_last_driver == -1) cdio_init();
1028
1029 /* Scan for a driver. */
1030 return scan_for_driver(cdio_device_drivers, psz_source, psz_access_mode);
1031 }
1032
1033 /*!
1034 Set the blocksize for subsequent reads.
1035 */
1036 driver_return_code_t
cdio_set_blocksize(const CdIo_t * p_cdio,int i_blocksize)1037 cdio_set_blocksize ( const CdIo_t *p_cdio, int i_blocksize )
1038 {
1039 if (!p_cdio) return DRIVER_OP_UNINIT;
1040 if (!p_cdio->op.set_blocksize) return DRIVER_OP_UNSUPPORTED;
1041 return p_cdio->op.set_blocksize(p_cdio->env, i_blocksize);
1042 }
1043
1044 /*!
1045 Set the drive speed.
1046
1047 @param p_cdio CD structure set by cdio_open().
1048 @param i_drive_speed speed in CD-ROM speed units. Note this
1049 not Kbs as would be used in the MMC spec or
1050 in mmc_set_speed(). To convert CD-ROM speed units
1051 to Kbs, multiply the number by 176 (for raw data)
1052 and by 150 (for filesystem data). On many CD-ROM
1053 drives, specifying a value too large will result
1054 in using the fastest speed.
1055
1056 @see mmc_set_speed and mmc_set_drive_speed
1057 */
1058 driver_return_code_t
cdio_set_speed(const CdIo_t * p_cdio,int i_speed)1059 cdio_set_speed (const CdIo_t *p_cdio, int i_speed)
1060 {
1061 if (!p_cdio) return DRIVER_OP_UNINIT;
1062 if (!p_cdio->op.set_speed) return DRIVER_OP_UNSUPPORTED;
1063 return p_cdio->op.set_speed(p_cdio->env, i_speed);
1064 }
1065
1066
1067 /*
1068 * Local variables:
1069 * c-file-style: "gnu"
1070 * tab-width: 8
1071 * indent-tabs-mode: nil
1072 * End:
1073 */
1074