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