2005-08-12 00:59:21 +04:00
/*
2008-04-10 01:17:39 +04:00
* cdrom_id - optical drive and media information prober
2005-08-12 00:59:21 +04:00
*
2012-11-12 22:36:23 +04:00
* Copyright ( C ) 2008 - 2010 Kay Sievers < kay @ vrfy . org >
2005-08-12 00:59:21 +04:00
*
2008-09-10 04:40:42 +04:00
* This program is free software : you can redistribute it and / or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation , either version 2 of the License , or
* ( at your option ) any later version .
2005-08-12 00:59:21 +04:00
*
2008-09-10 04:40:42 +04:00
* This program is distributed in the hope that it will be useful ,
* but WITHOUT ANY WARRANTY ; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE . See the
* GNU General Public License for more details .
2008-04-10 01:17:39 +04:00
*
2008-09-10 04:40:42 +04:00
* You should have received a copy of the GNU General Public License
* along with this program . If not , see < http : //www.gnu.org/licenses/>.
2005-08-12 00:59:21 +04:00
*/
# include <stdio.h>
2008-04-10 01:17:39 +04:00
# include <stddef.h>
2005-08-12 00:59:21 +04:00
# include <stdlib.h>
# include <unistd.h>
2006-01-09 23:18:00 +03:00
# include <string.h>
2008-04-10 01:17:39 +04:00
# include <limits.h>
# include <fcntl.h>
2005-08-12 00:59:21 +04:00
# include <errno.h>
2008-04-10 01:17:39 +04:00
# include <getopt.h>
2010-04-07 11:24:25 +04:00
# include <time.h>
2008-04-10 01:17:39 +04:00
# include <scsi/sg.h>
2005-08-12 00:59:21 +04:00
# include <sys/types.h>
# include <sys/stat.h>
2008-04-10 01:17:39 +04:00
# include <sys/time.h>
# include <sys/ioctl.h>
# include <linux/cdrom.h>
2008-07-30 03:45:23 +04:00
2009-06-10 00:47:48 +04:00
# include "libudev.h"
# include "libudev-private.h"
2005-08-12 00:59:21 +04:00
2011-06-18 22:54:47 +04:00
static bool debug ;
2005-08-12 22:37:56 +04:00
2013-12-14 16:09:07 +04:00
_printf_ ( 6 , 0 )
2008-09-06 17:45:31 +04:00
static void log_fn ( struct udev * udev , int priority ,
2012-01-10 04:34:15 +04:00
const char * file , int line , const char * fn ,
const char * format , va_list args )
2005-08-12 00:59:21 +04:00
{
2012-01-10 04:34:15 +04:00
if ( debug ) {
fprintf ( stderr , " %s: " , fn ) ;
vfprintf ( stderr , format , args ) ;
} else {
vsyslog ( priority , format , args ) ;
}
2005-08-12 00:59:21 +04:00
}
2008-04-10 01:17:39 +04:00
/* device info */
2012-01-10 19:37:41 +04:00
static unsigned int cd_cd_rom ;
static unsigned int cd_cd_r ;
static unsigned int cd_cd_rw ;
static unsigned int cd_dvd_rom ;
static unsigned int cd_dvd_r ;
static unsigned int cd_dvd_rw ;
static unsigned int cd_dvd_ram ;
static unsigned int cd_dvd_plus_r ;
static unsigned int cd_dvd_plus_rw ;
static unsigned int cd_dvd_plus_r_dl ;
static unsigned int cd_dvd_plus_rw_dl ;
static unsigned int cd_bd ;
static unsigned int cd_bd_r ;
static unsigned int cd_bd_re ;
static unsigned int cd_hddvd ;
static unsigned int cd_hddvd_r ;
static unsigned int cd_hddvd_rw ;
static unsigned int cd_mo ;
static unsigned int cd_mrw ;
static unsigned int cd_mrw_w ;
2008-04-10 01:17:39 +04:00
/* media info */
2012-01-10 19:37:41 +04:00
static unsigned int cd_media ;
static unsigned int cd_media_cd_rom ;
static unsigned int cd_media_cd_r ;
static unsigned int cd_media_cd_rw ;
static unsigned int cd_media_dvd_rom ;
static unsigned int cd_media_dvd_r ;
static unsigned int cd_media_dvd_rw ;
static unsigned int cd_media_dvd_rw_ro ; /* restricted overwrite mode */
static unsigned int cd_media_dvd_rw_seq ; /* sequential mode */
static unsigned int cd_media_dvd_ram ;
static unsigned int cd_media_dvd_plus_r ;
static unsigned int cd_media_dvd_plus_rw ;
static unsigned int cd_media_dvd_plus_r_dl ;
static unsigned int cd_media_dvd_plus_rw_dl ;
static unsigned int cd_media_bd ;
static unsigned int cd_media_bd_r ;
static unsigned int cd_media_bd_re ;
static unsigned int cd_media_hddvd ;
static unsigned int cd_media_hddvd_r ;
static unsigned int cd_media_hddvd_rw ;
static unsigned int cd_media_mo ;
static unsigned int cd_media_mrw ;
static unsigned int cd_media_mrw_w ;
2008-04-10 01:17:39 +04:00
2010-04-13 12:49:24 +04:00
static const char * cd_media_state = NULL ;
2012-01-10 19:37:41 +04:00
static unsigned int cd_media_session_next ;
static unsigned int cd_media_session_count ;
static unsigned int cd_media_track_count ;
static unsigned int cd_media_track_count_data ;
static unsigned int cd_media_track_count_audio ;
static unsigned long long int cd_media_session_last_offset ;
2008-04-10 01:17:39 +04:00
2012-01-10 04:34:15 +04:00
# define ERRCODE(s) ((((s)[2] & 0x0F) << 16) | ((s)[12] << 8) | ((s)[13]))
# define SK(errcode) (((errcode) >> 16) & 0xF)
# define ASC(errcode) (((errcode) >> 8) & 0xFF)
# define ASCQ(errcode) ((errcode) & 0xFF)
2008-04-10 01:17:39 +04:00
2012-01-10 19:37:41 +04:00
static bool is_mounted ( const char * device )
2010-03-18 13:14:32 +03:00
{
2012-01-10 04:34:15 +04:00
struct stat statbuf ;
FILE * fp ;
int maj , min ;
2012-01-10 19:37:41 +04:00
bool mounted = false ;
2012-01-10 04:34:15 +04:00
if ( stat ( device , & statbuf ) < 0 )
return - ENODEV ;
2012-07-05 19:33:24 +04:00
fp = fopen ( " /proc/self/mountinfo " , " re " ) ;
2012-01-10 04:34:15 +04:00
if ( fp = = NULL )
return - ENOSYS ;
while ( fscanf ( fp , " %*s %*s %i:%i %*[^ \n ] " , & maj , & min ) = = 2 ) {
if ( makedev ( maj , min ) = = statbuf . st_rdev ) {
2012-01-10 19:37:41 +04:00
mounted = true ;
2012-01-10 04:34:15 +04:00
break ;
}
}
fclose ( fp ) ;
return mounted ;
2010-03-18 13:14:32 +03:00
}
2012-04-04 07:18:14 +04:00
static void info_scsi_cmd_err ( struct udev * udev , const char * cmd , int err )
2008-04-10 01:17:39 +04:00
{
2012-01-10 04:34:15 +04:00
if ( err = = - 1 ) {
2013-12-24 19:39:37 +04:00
log_debug ( " %s failed " , cmd ) ;
2012-01-10 04:34:15 +04:00
return ;
}
2013-12-24 19:39:37 +04:00
log_debug ( " %s failed with SK=%Xh/ASC=%02Xh/ACQ=%02Xh " , cmd , SK ( err ) , ASC ( err ) , ASCQ ( err ) ) ;
2008-04-10 01:17:39 +04:00
}
struct scsi_cmd {
2012-01-10 04:34:15 +04:00
struct cdrom_generic_command cgc ;
union {
struct request_sense s ;
unsigned char u [ 18 ] ;
} _sense ;
struct sg_io_hdr sg_io ;
2008-04-10 01:17:39 +04:00
} ;
2011-06-18 22:54:47 +04:00
static void scsi_cmd_init ( struct udev * udev , struct scsi_cmd * cmd )
2010-04-15 22:07:07 +04:00
{
2014-01-31 09:51:32 +04:00
memzero ( cmd , sizeof ( struct scsi_cmd ) ) ;
2012-01-10 04:34:15 +04:00
cmd - > cgc . quiet = 1 ;
cmd - > cgc . sense = & cmd - > _sense . s ;
cmd - > sg_io . interface_id = ' S ' ;
cmd - > sg_io . mx_sb_len = sizeof ( cmd - > _sense ) ;
cmd - > sg_io . cmdp = cmd - > cgc . cmd ;
cmd - > sg_io . sbp = cmd - > _sense . u ;
cmd - > sg_io . flags = SG_FLAG_LUN_INHIBIT | SG_FLAG_DIRECT_IO ;
2010-04-15 22:07:07 +04:00
}
static void scsi_cmd_set ( struct udev * udev , struct scsi_cmd * cmd , size_t i , unsigned char arg )
2008-04-10 01:17:39 +04:00
{
2012-01-10 04:34:15 +04:00
cmd - > sg_io . cmd_len = i + 1 ;
cmd - > cgc . cmd [ i ] = arg ;
2008-04-10 01:17:39 +04:00
}
# define CHECK_CONDITION 0x01
2008-09-06 17:45:31 +04:00
static int scsi_cmd_run ( struct udev * udev , struct scsi_cmd * cmd , int fd , unsigned char * buf , size_t bufsize )
2008-04-10 01:17:39 +04:00
{
2012-01-10 04:34:15 +04:00
int ret = 0 ;
if ( bufsize > 0 ) {
cmd - > sg_io . dxferp = buf ;
cmd - > sg_io . dxfer_len = bufsize ;
cmd - > sg_io . dxfer_direction = SG_DXFER_FROM_DEV ;
} else {
cmd - > sg_io . dxfer_direction = SG_DXFER_NONE ;
}
if ( ioctl ( fd , SG_IO , & cmd - > sg_io ) )
return - 1 ;
if ( ( cmd - > sg_io . info & SG_INFO_OK_MASK ) ! = SG_INFO_OK ) {
errno = EIO ;
ret = - 1 ;
if ( cmd - > sg_io . masked_status & CHECK_CONDITION ) {
ret = ERRCODE ( cmd - > _sense . u ) ;
if ( ret = = 0 )
ret = - 1 ;
}
}
return ret ;
2008-04-10 01:17:39 +04:00
}
2011-06-18 22:54:47 +04:00
static int media_lock ( struct udev * udev , int fd , bool lock )
{
2012-01-10 04:34:15 +04:00
int err ;
2011-06-18 22:54:47 +04:00
2012-01-10 04:34:15 +04:00
/* disable the kernel's lock logic */
err = ioctl ( fd , CDROM_CLEAR_OPTIONS , CDO_LOCK ) ;
if ( err < 0 )
2013-12-24 19:39:37 +04:00
log_debug ( " CDROM_CLEAR_OPTIONS, CDO_LOCK failed " ) ;
2011-06-18 22:54:47 +04:00
2012-01-10 04:34:15 +04:00
err = ioctl ( fd , CDROM_LOCKDOOR , lock ? 1 : 0 ) ;
if ( err < 0 )
2013-12-24 19:39:37 +04:00
log_debug ( " CDROM_LOCKDOOR failed " ) ;
2011-06-18 22:54:47 +04:00
2012-01-10 04:34:15 +04:00
return err ;
2011-06-18 22:54:47 +04:00
}
static int media_eject ( struct udev * udev , int fd )
{
2012-01-10 04:34:15 +04:00
struct scsi_cmd sc ;
int err ;
scsi_cmd_init ( udev , & sc ) ;
scsi_cmd_set ( udev , & sc , 0 , 0x1b ) ;
scsi_cmd_set ( udev , & sc , 4 , 0x02 ) ;
scsi_cmd_set ( udev , & sc , 5 , 0 ) ;
err = scsi_cmd_run ( udev , & sc , fd , NULL , 0 ) ;
if ( ( err ! = 0 ) ) {
info_scsi_cmd_err ( udev , " START_STOP_UNIT " , err ) ;
return - 1 ;
}
return 0 ;
2011-06-18 22:54:47 +04:00
}
2008-09-06 17:45:31 +04:00
static int cd_capability_compat ( struct udev * udev , int fd )
2008-04-10 01:17:39 +04:00
{
2012-01-10 04:34:15 +04:00
int capability ;
capability = ioctl ( fd , CDROM_GET_CAPABILITY , NULL ) ;
if ( capability < 0 ) {
2013-12-24 19:39:37 +04:00
log_debug ( " CDROM_GET_CAPABILITY failed " ) ;
2012-01-10 04:34:15 +04:00
return - 1 ;
}
if ( capability & CDC_CD_R )
cd_cd_r = 1 ;
if ( capability & CDC_CD_RW )
cd_cd_rw = 1 ;
if ( capability & CDC_DVD )
cd_dvd_rom = 1 ;
if ( capability & CDC_DVD_R )
cd_dvd_r = 1 ;
if ( capability & CDC_DVD_RAM )
cd_dvd_ram = 1 ;
if ( capability & CDC_MRW )
cd_mrw = 1 ;
if ( capability & CDC_MRW_W )
cd_mrw_w = 1 ;
return 0 ;
2008-04-10 01:17:39 +04:00
}
2009-04-23 17:04:16 +04:00
static int cd_media_compat ( struct udev * udev , int fd )
{
2012-01-10 04:34:15 +04:00
if ( ioctl ( fd , CDROM_DRIVE_STATUS , CDSL_CURRENT ) ! = CDS_DISC_OK ) {
2013-12-24 19:39:37 +04:00
log_debug ( " CDROM_DRIVE_STATUS != CDS_DISC_OK " ) ;
2012-01-10 04:34:15 +04:00
return - 1 ;
}
cd_media = 1 ;
return 0 ;
2009-04-23 17:04:16 +04:00
}
2011-06-18 22:54:47 +04:00
static int cd_inquiry ( struct udev * udev , int fd )
{
2012-01-10 04:34:15 +04:00
struct scsi_cmd sc ;
unsigned char inq [ 128 ] ;
int err ;
scsi_cmd_init ( udev , & sc ) ;
scsi_cmd_set ( udev , & sc , 0 , 0x12 ) ;
scsi_cmd_set ( udev , & sc , 4 , 36 ) ;
scsi_cmd_set ( udev , & sc , 5 , 0 ) ;
err = scsi_cmd_run ( udev , & sc , fd , inq , 36 ) ;
if ( ( err ! = 0 ) ) {
info_scsi_cmd_err ( udev , " INQUIRY " , err ) ;
return - 1 ;
}
if ( ( inq [ 0 ] & 0x1F ) ! = 5 ) {
2013-12-24 19:39:37 +04:00
log_debug ( " not an MMC unit " ) ;
2012-01-10 04:34:15 +04:00
return - 1 ;
}
2013-12-24 19:39:37 +04:00
log_debug ( " INQUIRY: [%.8s][%.16s][%.4s] " , inq + 8 , inq + 16 , inq + 32 ) ;
2012-01-10 04:34:15 +04:00
return 0 ;
2008-04-10 01:17:39 +04:00
}
2011-03-15 19:05:00 +03:00
static void feature_profile_media ( struct udev * udev , int cur_profile )
{
2012-01-10 04:34:15 +04:00
switch ( cur_profile ) {
case 0x03 :
case 0x04 :
case 0x05 :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x " , cur_profile ) ;
2012-01-10 04:34:15 +04:00
cd_media = 1 ;
cd_media_mo = 1 ;
break ;
case 0x08 :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x media_cd_rom " , cur_profile ) ;
2012-01-10 04:34:15 +04:00
cd_media = 1 ;
cd_media_cd_rom = 1 ;
break ;
case 0x09 :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x media_cd_r " , cur_profile ) ;
2012-01-10 04:34:15 +04:00
cd_media = 1 ;
cd_media_cd_r = 1 ;
break ;
case 0x0a :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x media_cd_rw " , cur_profile ) ;
2012-01-10 04:34:15 +04:00
cd_media = 1 ;
cd_media_cd_rw = 1 ;
break ;
case 0x10 :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x media_dvd_ro " , cur_profile ) ;
2012-01-10 04:34:15 +04:00
cd_media = 1 ;
cd_media_dvd_rom = 1 ;
break ;
case 0x11 :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x media_dvd_r " , cur_profile ) ;
2012-01-10 04:34:15 +04:00
cd_media = 1 ;
cd_media_dvd_r = 1 ;
break ;
case 0x12 :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x media_dvd_ram " , cur_profile ) ;
2012-01-10 04:34:15 +04:00
cd_media = 1 ;
cd_media_dvd_ram = 1 ;
break ;
case 0x13 :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x media_dvd_rw_ro " , cur_profile ) ;
2012-01-10 04:34:15 +04:00
cd_media = 1 ;
cd_media_dvd_rw = 1 ;
cd_media_dvd_rw_ro = 1 ;
break ;
case 0x14 :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x media_dvd_rw_seq " , cur_profile ) ;
2012-01-10 04:34:15 +04:00
cd_media = 1 ;
cd_media_dvd_rw = 1 ;
cd_media_dvd_rw_seq = 1 ;
break ;
case 0x1B :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x media_dvd_plus_r " , cur_profile ) ;
2012-01-10 04:34:15 +04:00
cd_media = 1 ;
cd_media_dvd_plus_r = 1 ;
break ;
case 0x1A :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x media_dvd_plus_rw " , cur_profile ) ;
2012-01-10 04:34:15 +04:00
cd_media = 1 ;
cd_media_dvd_plus_rw = 1 ;
break ;
case 0x2A :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x media_dvd_plus_rw_dl " , cur_profile ) ;
2012-01-10 04:34:15 +04:00
cd_media = 1 ;
cd_media_dvd_plus_rw_dl = 1 ;
break ;
case 0x2B :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x media_dvd_plus_r_dl " , cur_profile ) ;
2012-01-10 04:34:15 +04:00
cd_media = 1 ;
cd_media_dvd_plus_r_dl = 1 ;
break ;
case 0x40 :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x media_bd " , cur_profile ) ;
2012-01-10 04:34:15 +04:00
cd_media = 1 ;
cd_media_bd = 1 ;
break ;
case 0x41 :
case 0x42 :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x media_bd_r " , cur_profile ) ;
2012-01-10 04:34:15 +04:00
cd_media = 1 ;
cd_media_bd_r = 1 ;
break ;
case 0x43 :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x media_bd_re " , cur_profile ) ;
2012-01-10 04:34:15 +04:00
cd_media = 1 ;
cd_media_bd_re = 1 ;
break ;
case 0x50 :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x media_hddvd " , cur_profile ) ;
2012-01-10 04:34:15 +04:00
cd_media = 1 ;
cd_media_hddvd = 1 ;
break ;
case 0x51 :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x media_hddvd_r " , cur_profile ) ;
2012-01-10 04:34:15 +04:00
cd_media = 1 ;
cd_media_hddvd_r = 1 ;
break ;
case 0x52 :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x media_hddvd_rw " , cur_profile ) ;
2012-01-10 04:34:15 +04:00
cd_media = 1 ;
cd_media_hddvd_rw = 1 ;
break ;
default :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x <ignored> " , cur_profile ) ;
2012-01-10 04:34:15 +04:00
break ;
}
2011-03-15 19:05:00 +03:00
}
2010-04-15 22:07:07 +04:00
static int feature_profiles ( struct udev * udev , const unsigned char * profiles , size_t size )
2008-04-10 01:17:39 +04:00
{
2012-01-10 04:34:15 +04:00
unsigned int i ;
for ( i = 0 ; i + 4 < = size ; i + = 4 ) {
int profile ;
profile = profiles [ i ] < < 8 | profiles [ i + 1 ] ;
switch ( profile ) {
case 0x03 :
case 0x04 :
case 0x05 :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x mo " , profile ) ;
2012-01-10 04:34:15 +04:00
cd_mo = 1 ;
break ;
case 0x08 :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x cd_rom " , profile ) ;
2012-01-10 04:34:15 +04:00
cd_cd_rom = 1 ;
break ;
case 0x09 :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x cd_r " , profile ) ;
2012-01-10 04:34:15 +04:00
cd_cd_r = 1 ;
break ;
case 0x0A :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x cd_rw " , profile ) ;
2012-01-10 04:34:15 +04:00
cd_cd_rw = 1 ;
break ;
case 0x10 :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x dvd_rom " , profile ) ;
2012-01-10 04:34:15 +04:00
cd_dvd_rom = 1 ;
break ;
case 0x12 :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x dvd_ram " , profile ) ;
2012-01-10 04:34:15 +04:00
cd_dvd_ram = 1 ;
break ;
case 0x13 :
case 0x14 :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x dvd_rw " , profile ) ;
2012-01-10 04:34:15 +04:00
cd_dvd_rw = 1 ;
break ;
case 0x1B :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x dvd_plus_r " , profile ) ;
2012-01-10 04:34:15 +04:00
cd_dvd_plus_r = 1 ;
break ;
case 0x1A :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x dvd_plus_rw " , profile ) ;
2012-01-10 04:34:15 +04:00
cd_dvd_plus_rw = 1 ;
break ;
case 0x2A :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x dvd_plus_rw_dl " , profile ) ;
2012-01-10 04:34:15 +04:00
cd_dvd_plus_rw_dl = 1 ;
break ;
case 0x2B :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x dvd_plus_r_dl " , profile ) ;
2012-01-10 04:34:15 +04:00
cd_dvd_plus_r_dl = 1 ;
break ;
case 0x40 :
cd_bd = 1 ;
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x bd " , profile ) ;
2012-01-10 04:34:15 +04:00
break ;
case 0x41 :
case 0x42 :
cd_bd_r = 1 ;
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x bd_r " , profile ) ;
2012-01-10 04:34:15 +04:00
break ;
case 0x43 :
cd_bd_re = 1 ;
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x bd_re " , profile ) ;
2012-01-10 04:34:15 +04:00
break ;
case 0x50 :
cd_hddvd = 1 ;
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x hddvd " , profile ) ;
2012-01-10 04:34:15 +04:00
break ;
case 0x51 :
cd_hddvd_r = 1 ;
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x hddvd_r " , profile ) ;
2012-01-10 04:34:15 +04:00
break ;
case 0x52 :
cd_hddvd_rw = 1 ;
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x hddvd_rw " , profile ) ;
2012-01-10 04:34:15 +04:00
break ;
default :
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x%02x <ignored> " , profile ) ;
2012-01-10 04:34:15 +04:00
break ;
}
}
return 0 ;
2010-04-15 22:07:07 +04:00
}
2011-03-15 19:05:00 +03:00
/* returns 0 if media was detected */
2010-08-08 19:57:47 +04:00
static int cd_profiles_old_mmc ( struct udev * udev , int fd )
{
2012-01-10 04:34:15 +04:00
struct scsi_cmd sc ;
int err ;
unsigned char header [ 32 ] ;
scsi_cmd_init ( udev , & sc ) ;
scsi_cmd_set ( udev , & sc , 0 , 0x51 ) ;
scsi_cmd_set ( udev , & sc , 8 , sizeof ( header ) ) ;
scsi_cmd_set ( udev , & sc , 9 , 0 ) ;
err = scsi_cmd_run ( udev , & sc , fd , header , sizeof ( header ) ) ;
if ( ( err ! = 0 ) ) {
info_scsi_cmd_err ( udev , " READ DISC INFORMATION " , err ) ;
if ( cd_media = = 1 ) {
2013-12-24 19:39:37 +04:00
log_debug ( " no current profile, but disc is present; assuming CD-ROM " ) ;
2012-01-10 04:34:15 +04:00
cd_media_cd_rom = 1 ;
2013-02-12 18:19:38 +04:00
cd_media_track_count = 1 ;
cd_media_track_count_data = 1 ;
2012-01-10 04:34:15 +04:00
return 0 ;
} else {
2013-12-24 19:39:37 +04:00
log_debug ( " no current profile, assuming no media " ) ;
2012-01-10 04:34:15 +04:00
return - 1 ;
}
} ;
cd_media = 1 ;
if ( header [ 2 ] & 16 ) {
cd_media_cd_rw = 1 ;
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x0a media_cd_rw " ) ;
2012-01-10 04:34:15 +04:00
} else if ( ( header [ 2 ] & 3 ) < 2 & & cd_cd_r ) {
cd_media_cd_r = 1 ;
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x09 media_cd_r " ) ;
2012-01-10 04:34:15 +04:00
} else {
cd_media_cd_rom = 1 ;
2013-12-24 19:39:37 +04:00
log_debug ( " profile 0x08 media_cd_rom " ) ;
2012-01-10 04:34:15 +04:00
}
return 0 ;
2010-08-08 19:57:47 +04:00
}
2011-03-15 19:05:00 +03:00
/* returns 0 if media was detected */
2010-04-15 22:07:07 +04:00
static int cd_profiles ( struct udev * udev , int fd )
{
2012-01-10 04:34:15 +04:00
struct scsi_cmd sc ;
unsigned char features [ 65530 ] ;
unsigned int cur_profile = 0 ;
unsigned int len ;
unsigned int i ;
int err ;
int ret ;
ret = - 1 ;
/* First query the current profile */
scsi_cmd_init ( udev , & sc ) ;
scsi_cmd_set ( udev , & sc , 0 , 0x46 ) ;
scsi_cmd_set ( udev , & sc , 8 , 8 ) ;
scsi_cmd_set ( udev , & sc , 9 , 0 ) ;
err = scsi_cmd_run ( udev , & sc , fd , features , 8 ) ;
if ( ( err ! = 0 ) ) {
info_scsi_cmd_err ( udev , " GET CONFIGURATION " , err ) ;
/* handle pre-MMC2 drives which do not support GET CONFIGURATION */
if ( SK ( err ) = = 0x5 & & ASC ( err ) = = 0x20 ) {
2013-12-24 19:39:37 +04:00
log_debug ( " drive is pre-MMC2 and does not support 46h get configuration command " ) ;
log_debug ( " trying to work around the problem " ) ;
2012-01-10 04:34:15 +04:00
ret = cd_profiles_old_mmc ( udev , fd ) ;
}
goto out ;
}
cur_profile = features [ 6 ] < < 8 | features [ 7 ] ;
if ( cur_profile > 0 ) {
2013-12-24 19:39:37 +04:00
log_debug ( " current profile 0x%02x " , cur_profile ) ;
2012-01-10 04:34:15 +04:00
feature_profile_media ( udev , cur_profile ) ;
ret = 0 ; /* we have media */
} else {
2013-12-24 19:39:37 +04:00
log_debug ( " no current profile, assuming no media " ) ;
2012-01-10 04:34:15 +04:00
}
len = features [ 0 ] < < 24 | features [ 1 ] < < 16 | features [ 2 ] < < 8 | features [ 3 ] ;
2013-12-24 19:39:37 +04:00
log_debug ( " GET CONFIGURATION: size of features buffer 0x%04x " , len ) ;
2012-01-10 04:34:15 +04:00
if ( len > sizeof ( features ) ) {
2013-12-24 19:39:37 +04:00
log_debug ( " can not get features in a single query, truncating " ) ;
2012-01-10 04:34:15 +04:00
len = sizeof ( features ) ;
} else if ( len < = 8 ) {
len = sizeof ( features ) ;
}
/* Now get the full feature buffer */
scsi_cmd_init ( udev , & sc ) ;
scsi_cmd_set ( udev , & sc , 0 , 0x46 ) ;
scsi_cmd_set ( udev , & sc , 7 , ( len > > 8 ) & 0xff ) ;
scsi_cmd_set ( udev , & sc , 8 , len & 0xff ) ;
scsi_cmd_set ( udev , & sc , 9 , 0 ) ;
err = scsi_cmd_run ( udev , & sc , fd , features , len ) ;
if ( ( err ! = 0 ) ) {
info_scsi_cmd_err ( udev , " GET CONFIGURATION " , err ) ;
return - 1 ;
}
/* parse the length once more, in case the drive decided to have other features suddenly :) */
len = features [ 0 ] < < 24 | features [ 1 ] < < 16 | features [ 2 ] < < 8 | features [ 3 ] ;
2013-12-24 19:39:37 +04:00
log_debug ( " GET CONFIGURATION: size of features buffer 0x%04x " , len ) ;
2012-01-10 04:34:15 +04:00
if ( len > sizeof ( features ) ) {
2013-12-24 19:39:37 +04:00
log_debug ( " can not get features in a single query, truncating " ) ;
2012-01-10 04:34:15 +04:00
len = sizeof ( features ) ;
}
/* device features */
for ( i = 8 ; i + 4 < len ; i + = ( 4 + features [ i + 3 ] ) ) {
unsigned int feature ;
feature = features [ i ] < < 8 | features [ i + 1 ] ;
switch ( feature ) {
case 0x00 :
2013-12-24 19:39:37 +04:00
log_debug ( " GET CONFIGURATION: feature 'profiles', with %i entries " , features [ i + 3 ] / 4 ) ;
2012-01-10 04:34:15 +04:00
feature_profiles ( udev , & features [ i ] + 4 , features [ i + 3 ] ) ;
break ;
default :
2013-12-24 19:39:37 +04:00
log_debug ( " GET CONFIGURATION: feature 0x%04x <ignored>, with 0x%02x bytes " , feature , features [ i + 3 ] ) ;
2012-01-10 04:34:15 +04:00
break ;
}
}
2011-03-15 19:05:00 +03:00
out :
2012-01-10 04:34:15 +04:00
return ret ;
2008-04-10 01:17:39 +04:00
}
2008-09-06 17:45:31 +04:00
static int cd_media_info ( struct udev * udev , int fd )
2008-04-10 01:17:39 +04:00
{
2012-01-10 04:34:15 +04:00
struct scsi_cmd sc ;
unsigned char header [ 32 ] ;
static const char * media_status [ ] = {
" blank " ,
" appendable " ,
" complete " ,
" other "
} ;
int err ;
scsi_cmd_init ( udev , & sc ) ;
scsi_cmd_set ( udev , & sc , 0 , 0x51 ) ;
scsi_cmd_set ( udev , & sc , 8 , sizeof ( header ) & 0xff ) ;
scsi_cmd_set ( udev , & sc , 9 , 0 ) ;
err = scsi_cmd_run ( udev , & sc , fd , header , sizeof ( header ) ) ;
if ( ( err ! = 0 ) ) {
info_scsi_cmd_err ( udev , " READ DISC INFORMATION " , err ) ;
return - 1 ;
} ;
cd_media = 1 ;
2013-12-24 19:39:37 +04:00
log_debug ( " disk type %02x " , header [ 8 ] ) ;
log_debug ( " hardware reported media status: %s " , media_status [ header [ 2 ] & 3 ] ) ;
2012-01-10 04:34:15 +04:00
/* exclude plain CDROM, some fake cdroms return 0 for "blank" media here */
if ( ! cd_media_cd_rom )
cd_media_state = media_status [ header [ 2 ] & 3 ] ;
/* fresh DVD-RW in restricted overwite mode reports itself as
* " appendable " ; change it to " blank " to make it consistent with what
* gets reported after blanking , and what userspace expects */
if ( cd_media_dvd_rw_ro & & ( header [ 2 ] & 3 ) = = 1 )
cd_media_state = media_status [ 0 ] ;
/* DVD+RW discs (and DVD-RW in restricted mode) once formatted are
* always " complete " , DVD - RAM are " other " or " complete " if the disc is
* write protected ; we need to check the contents if it is blank */
if ( ( cd_media_dvd_rw_ro | | cd_media_dvd_plus_rw | | cd_media_dvd_plus_rw_dl | | cd_media_dvd_ram ) & & ( header [ 2 ] & 3 ) > 1 ) {
unsigned char buffer [ 32 * 2048 ] ;
unsigned char result , len ;
int block , offset ;
if ( cd_media_dvd_ram ) {
/* a write protected dvd-ram may report "complete" status */
unsigned char dvdstruct [ 8 ] ;
unsigned char format [ 12 ] ;
scsi_cmd_init ( udev , & sc ) ;
scsi_cmd_set ( udev , & sc , 0 , 0xAD ) ;
scsi_cmd_set ( udev , & sc , 7 , 0xC0 ) ;
scsi_cmd_set ( udev , & sc , 9 , sizeof ( dvdstruct ) ) ;
scsi_cmd_set ( udev , & sc , 11 , 0 ) ;
err = scsi_cmd_run ( udev , & sc , fd , dvdstruct , sizeof ( dvdstruct ) ) ;
if ( ( err ! = 0 ) ) {
info_scsi_cmd_err ( udev , " READ DVD STRUCTURE " , err ) ;
return - 1 ;
}
if ( dvdstruct [ 4 ] & 0x02 ) {
cd_media_state = media_status [ 2 ] ;
2013-12-24 19:39:37 +04:00
log_debug ( " write-protected DVD-RAM media inserted " ) ;
2012-01-10 04:34:15 +04:00
goto determined ;
}
/* let's make sure we don't try to read unformatted media */
scsi_cmd_init ( udev , & sc ) ;
scsi_cmd_set ( udev , & sc , 0 , 0x23 ) ;
scsi_cmd_set ( udev , & sc , 8 , sizeof ( format ) ) ;
scsi_cmd_set ( udev , & sc , 9 , 0 ) ;
err = scsi_cmd_run ( udev , & sc , fd , format , sizeof ( format ) ) ;
if ( ( err ! = 0 ) ) {
info_scsi_cmd_err ( udev , " READ DVD FORMAT CAPACITIES " , err ) ;
return - 1 ;
}
len = format [ 3 ] ;
if ( len & 7 | | len < 16 ) {
2013-12-24 19:39:37 +04:00
log_debug ( " invalid format capacities length " ) ;
2012-01-10 04:34:15 +04:00
return - 1 ;
}
switch ( format [ 8 ] & 3 ) {
case 1 :
2013-12-24 19:39:37 +04:00
log_debug ( " unformatted DVD-RAM media inserted " ) ;
2012-01-10 04:34:15 +04:00
/* This means that last format was interrupted
* or failed , blank dvd - ram discs are factory
* formatted . Take no action here as it takes
* quite a while to reformat a dvd - ram and it ' s
* not automatically started */
goto determined ;
case 2 :
2013-12-24 19:39:37 +04:00
log_debug ( " formatted DVD-RAM media inserted " ) ;
2012-01-10 04:34:15 +04:00
break ;
case 3 :
cd_media = 0 ; //return no media
2013-12-24 19:39:37 +04:00
log_debug ( " format capacities returned no media " ) ;
2012-01-10 04:34:15 +04:00
return - 1 ;
}
}
/* Take a closer look at formatted media (unformatted DVD+RW
* has " blank " status " , DVD-RAM was examined earlier) and check
* for ISO and UDF PVDs or a fs superblock presence and do it
* in one ioctl ( we need just sectors 0 and 16 ) */
scsi_cmd_init ( udev , & sc ) ;
scsi_cmd_set ( udev , & sc , 0 , 0x28 ) ;
scsi_cmd_set ( udev , & sc , 5 , 0 ) ;
scsi_cmd_set ( udev , & sc , 8 , 32 ) ;
scsi_cmd_set ( udev , & sc , 9 , 0 ) ;
err = scsi_cmd_run ( udev , & sc , fd , buffer , sizeof ( buffer ) ) ;
if ( ( err ! = 0 ) ) {
cd_media = 0 ;
info_scsi_cmd_err ( udev , " READ FIRST 32 BLOCKS " , err ) ;
return - 1 ;
}
/* if any non-zero data is found in sector 16 (iso and udf) or
* eventually 0 ( fat32 boot sector , ext2 superblock , etc ) , disc
* is assumed non - blank */
result = 0 ;
for ( block = 32768 ; block > = 0 & & ! result ; block - = 32768 ) {
offset = block ;
while ( offset < ( block + 2048 ) & & ! result ) {
result = buffer [ offset ] ;
offset + + ;
}
}
if ( ! result ) {
cd_media_state = media_status [ 0 ] ;
2013-12-24 19:39:37 +04:00
log_debug ( " no data in blocks 0 or 16, assuming blank " ) ;
2012-01-10 04:34:15 +04:00
} else {
2013-12-24 19:39:37 +04:00
log_debug ( " data in blocks 0 or 16, assuming complete " ) ;
2012-01-10 04:34:15 +04:00
}
}
2010-08-08 19:47:08 +04:00
determined :
2012-01-10 04:34:15 +04:00
/* "other" is e. g. DVD-RAM, can't append sessions there; DVDs in
* restricted overwrite mode can never append , only in sequential mode */
if ( ( header [ 2 ] & 3 ) < 2 & & ! cd_media_dvd_rw_ro )
cd_media_session_next = header [ 10 ] < < 8 | header [ 5 ] ;
cd_media_session_count = header [ 9 ] < < 8 | header [ 4 ] ;
cd_media_track_count = header [ 11 ] < < 8 | header [ 6 ] ;
return 0 ;
2008-04-10 01:17:39 +04:00
}
2008-09-06 17:45:31 +04:00
static int cd_media_toc ( struct udev * udev , int fd )
2008-04-10 01:17:39 +04:00
{
2012-01-10 04:34:15 +04:00
struct scsi_cmd sc ;
unsigned char header [ 12 ] ;
unsigned char toc [ 65536 ] ;
unsigned int len , i , num_tracks ;
unsigned char * p ;
int err ;
scsi_cmd_init ( udev , & sc ) ;
scsi_cmd_set ( udev , & sc , 0 , 0x43 ) ;
scsi_cmd_set ( udev , & sc , 6 , 1 ) ;
scsi_cmd_set ( udev , & sc , 8 , sizeof ( header ) & 0xff ) ;
scsi_cmd_set ( udev , & sc , 9 , 0 ) ;
err = scsi_cmd_run ( udev , & sc , fd , header , sizeof ( header ) ) ;
if ( ( err ! = 0 ) ) {
info_scsi_cmd_err ( udev , " READ TOC " , err ) ;
return - 1 ;
}
len = ( header [ 0 ] < < 8 | header [ 1 ] ) + 2 ;
2013-12-24 19:39:37 +04:00
log_debug ( " READ TOC: len: %d, start track: %d, end track: %d " , len , header [ 2 ] , header [ 3 ] ) ;
2012-01-10 04:34:15 +04:00
if ( len > sizeof ( toc ) )
return - 1 ;
if ( len < 2 )
return - 1 ;
/* 2: first track, 3: last track */
num_tracks = header [ 3 ] - header [ 2 ] + 1 ;
/* empty media has no tracks */
if ( len < 8 )
return 0 ;
scsi_cmd_init ( udev , & sc ) ;
scsi_cmd_set ( udev , & sc , 0 , 0x43 ) ;
scsi_cmd_set ( udev , & sc , 6 , header [ 2 ] ) ; /* First Track/Session Number */
scsi_cmd_set ( udev , & sc , 7 , ( len > > 8 ) & 0xff ) ;
scsi_cmd_set ( udev , & sc , 8 , len & 0xff ) ;
scsi_cmd_set ( udev , & sc , 9 , 0 ) ;
err = scsi_cmd_run ( udev , & sc , fd , toc , len ) ;
if ( ( err ! = 0 ) ) {
info_scsi_cmd_err ( udev , " READ TOC (tracks) " , err ) ;
return - 1 ;
}
/* Take care to not iterate beyond the last valid track as specified in
* the TOC , but also avoid going beyond the TOC length , just in case
* the last track number is invalidly large */
for ( p = toc + 4 , i = 4 ; i < len - 8 & & num_tracks > 0 ; i + = 8 , p + = 8 , - - num_tracks ) {
unsigned int block ;
unsigned int is_data_track ;
is_data_track = ( p [ 1 ] & 0x04 ) ! = 0 ;
block = p [ 4 ] < < 24 | p [ 5 ] < < 16 | p [ 6 ] < < 8 | p [ 7 ] ;
2013-12-24 19:39:37 +04:00
log_debug ( " track=%u info=0x%x(%s) start_block=%u " ,
2012-01-10 04:34:15 +04:00
p [ 2 ] , p [ 1 ] & 0x0f , is_data_track ? " data " : " audio " , block ) ;
if ( is_data_track )
cd_media_track_count_data + + ;
else
cd_media_track_count_audio + + ;
}
scsi_cmd_init ( udev , & sc ) ;
scsi_cmd_set ( udev , & sc , 0 , 0x43 ) ;
scsi_cmd_set ( udev , & sc , 2 , 1 ) ; /* Session Info */
scsi_cmd_set ( udev , & sc , 8 , sizeof ( header ) ) ;
scsi_cmd_set ( udev , & sc , 9 , 0 ) ;
err = scsi_cmd_run ( udev , & sc , fd , header , sizeof ( header ) ) ;
if ( ( err ! = 0 ) ) {
info_scsi_cmd_err ( udev , " READ TOC (multi session) " , err ) ;
return - 1 ;
}
len = header [ 4 + 4 ] < < 24 | header [ 4 + 5 ] < < 16 | header [ 4 + 6 ] < < 8 | header [ 4 + 7 ] ;
2013-12-24 19:39:37 +04:00
log_debug ( " last track %u starts at block %u " , header [ 4 + 2 ] , len ) ;
2012-01-10 04:34:15 +04:00
cd_media_session_last_offset = ( unsigned long long int ) len * 2048 ;
return 0 ;
2008-04-10 01:17:39 +04:00
}
2005-08-12 00:59:21 +04:00
int main ( int argc , char * argv [ ] )
{
2012-01-10 04:34:15 +04:00
struct udev * udev ;
static const struct option options [ ] = {
{ " lock-media " , no_argument , NULL , ' l ' } ,
{ " unlock-media " , no_argument , NULL , ' u ' } ,
{ " eject-media " , no_argument , NULL , ' e ' } ,
{ " debug " , no_argument , NULL , ' d ' } ,
{ " help " , no_argument , NULL , ' h ' } ,
{ }
} ;
bool eject = false ;
bool lock = false ;
bool unlock = false ;
const char * node = NULL ;
int fd = - 1 ;
int cnt ;
int rc = 0 ;
udev = udev_new ( ) ;
if ( udev = = NULL )
goto exit ;
2012-04-08 18:06:20 +04:00
log_open ( ) ;
2012-01-10 04:34:15 +04:00
udev_set_log_fn ( udev , log_fn ) ;
while ( 1 ) {
int option ;
option = getopt_long ( argc , argv , " deluh " , options , NULL ) ;
if ( option = = - 1 )
break ;
switch ( option ) {
case ' l ' :
lock = true ;
break ;
case ' u ' :
unlock = true ;
break ;
case ' e ' :
eject = true ;
break ;
case ' d ' :
debug = true ;
2012-07-26 14:03:25 +04:00
log_set_max_level ( LOG_DEBUG ) ;
udev_set_log_priority ( udev , LOG_DEBUG ) ;
2012-01-10 04:34:15 +04:00
break ;
case ' h ' :
printf ( " Usage: cdrom_id [options] <device> \n "
" --lock-media lock the media (to enable eject request events) \n "
" --unlock-media unlock the media \n "
" --eject-media eject the media \n "
" --debug debug to stderr \n "
" --help print this help text \n \n " ) ;
goto exit ;
default :
rc = 1 ;
goto exit ;
}
}
node = argv [ optind ] ;
if ( ! node ) {
2013-12-24 19:39:37 +04:00
log_error ( " no device " ) ;
2012-01-10 04:34:15 +04:00
fprintf ( stderr , " no device \n " ) ;
rc = 1 ;
goto exit ;
}
srand ( ( unsigned int ) getpid ( ) ) ;
for ( cnt = 20 ; cnt > 0 ; cnt - - ) {
struct timespec duration ;
2014-02-13 17:59:56 +04:00
fd = open ( node , O_RDONLY | O_NONBLOCK | O_CLOEXEC | ( is_mounted ( node ) ? 0 : O_EXCL ) ) ;
2012-01-10 04:34:15 +04:00
if ( fd > = 0 | | errno ! = EBUSY )
break ;
duration . tv_sec = 0 ;
duration . tv_nsec = ( 100 * 1000 * 1000 ) + ( rand ( ) % 100 * 1000 * 1000 ) ;
nanosleep ( & duration , NULL ) ;
}
if ( fd < 0 ) {
2013-12-24 19:39:37 +04:00
log_debug ( " unable to open '%s' " , node ) ;
2012-01-10 04:34:15 +04:00
fprintf ( stderr , " unable to open '%s' \n " , node ) ;
rc = 1 ;
goto exit ;
}
2013-12-24 19:39:37 +04:00
log_debug ( " probing: '%s' " , node ) ;
2012-01-10 04:34:15 +04:00
/* same data as original cdrom_id */
if ( cd_capability_compat ( udev , fd ) < 0 ) {
rc = 1 ;
goto exit ;
}
/* check for media - don't bail if there's no media as we still need to
2009-11-10 20:32:38 +03:00
* to read profiles */
2012-01-10 04:34:15 +04:00
cd_media_compat ( udev , fd ) ;
2009-04-23 17:04:16 +04:00
2012-01-10 04:34:15 +04:00
/* check if drive talks MMC */
if ( cd_inquiry ( udev , fd ) < 0 )
goto work ;
2005-08-12 00:59:21 +04:00
2012-01-10 04:34:15 +04:00
/* read drive and possibly current profile */
if ( cd_profiles ( udev , fd ) ! = 0 )
goto work ;
2008-04-10 01:17:39 +04:00
2012-01-10 04:34:15 +04:00
/* at this point we are guaranteed to have media in the drive - find out more about it */
2011-03-15 19:05:00 +03:00
2012-01-10 04:34:15 +04:00
/* get session/track info */
cd_media_toc ( udev , fd ) ;
2010-04-15 23:25:57 +04:00
2012-01-10 04:34:15 +04:00
/* get writable media state */
cd_media_info ( udev , fd ) ;
2010-08-11 17:20:31 +04:00
2011-06-18 22:54:47 +04:00
work :
2012-01-10 04:34:15 +04:00
/* lock the media, so we enable eject button events */
if ( lock & & cd_media ) {
2013-12-24 19:39:37 +04:00
log_debug ( " PREVENT_ALLOW_MEDIUM_REMOVAL (lock) " ) ;
2012-01-10 04:34:15 +04:00
media_lock ( udev , fd , true ) ;
}
if ( unlock & & cd_media ) {
2013-12-24 19:39:37 +04:00
log_debug ( " PREVENT_ALLOW_MEDIUM_REMOVAL (unlock) " ) ;
2012-01-10 04:34:15 +04:00
media_lock ( udev , fd , false ) ;
}
if ( eject ) {
2013-12-24 19:39:37 +04:00
log_debug ( " PREVENT_ALLOW_MEDIUM_REMOVAL (unlock) " ) ;
2012-01-10 04:34:15 +04:00
media_lock ( udev , fd , false ) ;
2013-12-24 19:39:37 +04:00
log_debug ( " START_STOP_UNIT (eject) " ) ;
2012-01-10 04:34:15 +04:00
media_eject ( udev , fd ) ;
}
printf ( " ID_CDROM=1 \n " ) ;
if ( cd_cd_rom )
printf ( " ID_CDROM_CD=1 \n " ) ;
if ( cd_cd_r )
printf ( " ID_CDROM_CD_R=1 \n " ) ;
if ( cd_cd_rw )
printf ( " ID_CDROM_CD_RW=1 \n " ) ;
if ( cd_dvd_rom )
printf ( " ID_CDROM_DVD=1 \n " ) ;
if ( cd_dvd_r )
printf ( " ID_CDROM_DVD_R=1 \n " ) ;
if ( cd_dvd_rw )
printf ( " ID_CDROM_DVD_RW=1 \n " ) ;
if ( cd_dvd_ram )
printf ( " ID_CDROM_DVD_RAM=1 \n " ) ;
if ( cd_dvd_plus_r )
printf ( " ID_CDROM_DVD_PLUS_R=1 \n " ) ;
if ( cd_dvd_plus_rw )
printf ( " ID_CDROM_DVD_PLUS_RW=1 \n " ) ;
if ( cd_dvd_plus_r_dl )
printf ( " ID_CDROM_DVD_PLUS_R_DL=1 \n " ) ;
if ( cd_dvd_plus_rw_dl )
printf ( " ID_CDROM_DVD_PLUS_RW_DL=1 \n " ) ;
if ( cd_bd )
printf ( " ID_CDROM_BD=1 \n " ) ;
if ( cd_bd_r )
printf ( " ID_CDROM_BD_R=1 \n " ) ;
if ( cd_bd_re )
printf ( " ID_CDROM_BD_RE=1 \n " ) ;
if ( cd_hddvd )
printf ( " ID_CDROM_HDDVD=1 \n " ) ;
if ( cd_hddvd_r )
printf ( " ID_CDROM_HDDVD_R=1 \n " ) ;
if ( cd_hddvd_rw )
printf ( " ID_CDROM_HDDVD_RW=1 \n " ) ;
if ( cd_mo )
printf ( " ID_CDROM_MO=1 \n " ) ;
if ( cd_mrw )
printf ( " ID_CDROM_MRW=1 \n " ) ;
if ( cd_mrw_w )
printf ( " ID_CDROM_MRW_W=1 \n " ) ;
if ( cd_media )
printf ( " ID_CDROM_MEDIA=1 \n " ) ;
if ( cd_media_mo )
printf ( " ID_CDROM_MEDIA_MO=1 \n " ) ;
if ( cd_media_mrw )
printf ( " ID_CDROM_MEDIA_MRW=1 \n " ) ;
if ( cd_media_mrw_w )
printf ( " ID_CDROM_MEDIA_MRW_W=1 \n " ) ;
if ( cd_media_cd_rom )
printf ( " ID_CDROM_MEDIA_CD=1 \n " ) ;
if ( cd_media_cd_r )
printf ( " ID_CDROM_MEDIA_CD_R=1 \n " ) ;
if ( cd_media_cd_rw )
printf ( " ID_CDROM_MEDIA_CD_RW=1 \n " ) ;
if ( cd_media_dvd_rom )
printf ( " ID_CDROM_MEDIA_DVD=1 \n " ) ;
if ( cd_media_dvd_r )
printf ( " ID_CDROM_MEDIA_DVD_R=1 \n " ) ;
if ( cd_media_dvd_ram )
printf ( " ID_CDROM_MEDIA_DVD_RAM=1 \n " ) ;
if ( cd_media_dvd_rw )
printf ( " ID_CDROM_MEDIA_DVD_RW=1 \n " ) ;
if ( cd_media_dvd_plus_r )
printf ( " ID_CDROM_MEDIA_DVD_PLUS_R=1 \n " ) ;
if ( cd_media_dvd_plus_rw )
printf ( " ID_CDROM_MEDIA_DVD_PLUS_RW=1 \n " ) ;
if ( cd_media_dvd_plus_rw_dl )
printf ( " ID_CDROM_MEDIA_DVD_PLUS_RW_DL=1 \n " ) ;
if ( cd_media_dvd_plus_r_dl )
printf ( " ID_CDROM_MEDIA_DVD_PLUS_R_DL=1 \n " ) ;
if ( cd_media_bd )
printf ( " ID_CDROM_MEDIA_BD=1 \n " ) ;
if ( cd_media_bd_r )
printf ( " ID_CDROM_MEDIA_BD_R=1 \n " ) ;
if ( cd_media_bd_re )
printf ( " ID_CDROM_MEDIA_BD_RE=1 \n " ) ;
if ( cd_media_hddvd )
printf ( " ID_CDROM_MEDIA_HDDVD=1 \n " ) ;
if ( cd_media_hddvd_r )
printf ( " ID_CDROM_MEDIA_HDDVD_R=1 \n " ) ;
if ( cd_media_hddvd_rw )
printf ( " ID_CDROM_MEDIA_HDDVD_RW=1 \n " ) ;
if ( cd_media_state ! = NULL )
printf ( " ID_CDROM_MEDIA_STATE=%s \n " , cd_media_state ) ;
if ( cd_media_session_next > 0 )
printf ( " ID_CDROM_MEDIA_SESSION_NEXT=%d \n " , cd_media_session_next ) ;
if ( cd_media_session_count > 0 )
printf ( " ID_CDROM_MEDIA_SESSION_COUNT=%d \n " , cd_media_session_count ) ;
if ( cd_media_session_count > 1 & & cd_media_session_last_offset > 0 )
printf ( " ID_CDROM_MEDIA_SESSION_LAST_OFFSET=%llu \n " , cd_media_session_last_offset ) ;
if ( cd_media_track_count > 0 )
printf ( " ID_CDROM_MEDIA_TRACK_COUNT=%d \n " , cd_media_track_count ) ;
if ( cd_media_track_count_audio > 0 )
printf ( " ID_CDROM_MEDIA_TRACK_COUNT_AUDIO=%d \n " , cd_media_track_count_audio ) ;
if ( cd_media_track_count_data > 0 )
printf ( " ID_CDROM_MEDIA_TRACK_COUNT_DATA=%d \n " , cd_media_track_count_data ) ;
2005-08-12 00:59:21 +04:00
exit :
2012-01-10 04:34:15 +04:00
if ( fd > = 0 )
close ( fd ) ;
udev_unref ( udev ) ;
2012-04-08 18:06:20 +04:00
log_close ( ) ;
2012-01-10 04:34:15 +04:00
return rc ;
2005-08-12 00:59:21 +04:00
}