| File: | build-scan/../src/udev/cdrom_id/cdrom_id.c |
| Warning: | line 807, column 39 The left operand of '&' is a garbage value |
Press '?' to see keyboard shortcuts
Keyboard shortcuts:
| 1 | /* SPDX-License-Identifier: GPL-2.0+ */ | |||
| 2 | /* | |||
| 3 | * cdrom_id - optical drive and media information prober | |||
| 4 | * | |||
| 5 | * | |||
| 6 | */ | |||
| 7 | ||||
| 8 | #include <errno(*__errno_location ()).h> | |||
| 9 | #include <fcntl.h> | |||
| 10 | #include <getopt.h> | |||
| 11 | #include <limits.h> | |||
| 12 | #include <linux1/cdrom.h> | |||
| 13 | #include <scsi/sg.h> | |||
| 14 | #include <stddef.h> | |||
| 15 | #include <stdio.h> | |||
| 16 | #include <stdlib.h> | |||
| 17 | #include <string.h> | |||
| 18 | #include <sys/ioctl.h> | |||
| 19 | #include <sys/stat.h> | |||
| 20 | #include <sys/time.h> | |||
| 21 | #include <sys/types.h> | |||
| 22 | #include <time.h> | |||
| 23 | #include <unistd.h> | |||
| 24 | ||||
| 25 | #include "libudev.h" | |||
| 26 | ||||
| 27 | #include "libudev-private.h" | |||
| 28 | #include "random-util.h" | |||
| 29 | #include "udev-util.h" | |||
| 30 | ||||
| 31 | /* device info */ | |||
| 32 | static unsigned int cd_cd_rom; | |||
| 33 | static unsigned int cd_cd_r; | |||
| 34 | static unsigned int cd_cd_rw; | |||
| 35 | static unsigned int cd_dvd_rom; | |||
| 36 | static unsigned int cd_dvd_r; | |||
| 37 | static unsigned int cd_dvd_rw; | |||
| 38 | static unsigned int cd_dvd_ram; | |||
| 39 | static unsigned int cd_dvd_plus_r; | |||
| 40 | static unsigned int cd_dvd_plus_rw; | |||
| 41 | static unsigned int cd_dvd_plus_r_dl; | |||
| 42 | static unsigned int cd_dvd_plus_rw_dl; | |||
| 43 | static unsigned int cd_bd; | |||
| 44 | static unsigned int cd_bd_r; | |||
| 45 | static unsigned int cd_bd_re; | |||
| 46 | static unsigned int cd_hddvd; | |||
| 47 | static unsigned int cd_hddvd_r; | |||
| 48 | static unsigned int cd_hddvd_rw; | |||
| 49 | static unsigned int cd_mo; | |||
| 50 | static unsigned int cd_mrw; | |||
| 51 | static unsigned int cd_mrw_w; | |||
| 52 | ||||
| 53 | /* media info */ | |||
| 54 | static unsigned int cd_media; | |||
| 55 | static unsigned int cd_media_cd_rom; | |||
| 56 | static unsigned int cd_media_cd_r; | |||
| 57 | static unsigned int cd_media_cd_rw; | |||
| 58 | static unsigned int cd_media_dvd_rom; | |||
| 59 | static unsigned int cd_media_dvd_r; | |||
| 60 | static unsigned int cd_media_dvd_rw; | |||
| 61 | static unsigned int cd_media_dvd_rw_ro; /* restricted overwrite mode */ | |||
| 62 | static unsigned int cd_media_dvd_rw_seq; /* sequential mode */ | |||
| 63 | static unsigned int cd_media_dvd_ram; | |||
| 64 | static unsigned int cd_media_dvd_plus_r; | |||
| 65 | static unsigned int cd_media_dvd_plus_rw; | |||
| 66 | static unsigned int cd_media_dvd_plus_r_dl; | |||
| 67 | static unsigned int cd_media_dvd_plus_rw_dl; | |||
| 68 | static unsigned int cd_media_bd; | |||
| 69 | static unsigned int cd_media_bd_r; | |||
| 70 | static unsigned int cd_media_bd_re; | |||
| 71 | static unsigned int cd_media_hddvd; | |||
| 72 | static unsigned int cd_media_hddvd_r; | |||
| 73 | static unsigned int cd_media_hddvd_rw; | |||
| 74 | static unsigned int cd_media_mo; | |||
| 75 | static unsigned int cd_media_mrw; | |||
| 76 | static unsigned int cd_media_mrw_w; | |||
| 77 | ||||
| 78 | static const char *cd_media_state = NULL((void*)0); | |||
| 79 | static unsigned int cd_media_session_next; | |||
| 80 | static unsigned int cd_media_session_count; | |||
| 81 | static unsigned int cd_media_track_count; | |||
| 82 | static unsigned int cd_media_track_count_data; | |||
| 83 | static unsigned int cd_media_track_count_audio; | |||
| 84 | static unsigned long long int cd_media_session_last_offset; | |||
| 85 | ||||
| 86 | #define ERRCODE(s)((((s)[2] & 0x0F) << 16) | ((s)[12] << 8) | ( (s)[13])) ((((s)[2] & 0x0F) << 16) | ((s)[12] << 8) | ((s)[13])) | |||
| 87 | #define SK(errcode)(((errcode) >> 16) & 0xF) (((errcode) >> 16) & 0xF) | |||
| 88 | #define ASC(errcode)(((errcode) >> 8) & 0xFF) (((errcode) >> 8) & 0xFF) | |||
| 89 | #define ASCQ(errcode)((errcode) & 0xFF) ((errcode) & 0xFF) | |||
| 90 | ||||
| 91 | static bool_Bool is_mounted(const char *device) | |||
| 92 | { | |||
| 93 | struct stat statbuf; | |||
| 94 | FILE *fp; | |||
| 95 | int maj, min; | |||
| 96 | bool_Bool mounted = false0; | |||
| 97 | ||||
| 98 | if (stat(device, &statbuf) < 0) | |||
| 99 | return false0; | |||
| 100 | ||||
| 101 | fp = fopen("/proc/self/mountinfo", "re"); | |||
| 102 | if (fp == NULL((void*)0)) | |||
| 103 | return false0; | |||
| 104 | while (fscanf(fp, "%*s %*s %i:%i %*[^\n]", &maj, &min) == 2) { | |||
| 105 | if (makedev(maj, min)gnu_dev_makedev (maj, min) == statbuf.st_rdev) { | |||
| 106 | mounted = true1; | |||
| 107 | break; | |||
| 108 | } | |||
| 109 | } | |||
| 110 | fclose(fp); | |||
| 111 | return mounted; | |||
| 112 | } | |||
| 113 | ||||
| 114 | static void info_scsi_cmd_err(struct udev *udev, const char *cmd, int err) | |||
| 115 | { | |||
| 116 | if (err == -1) { | |||
| 117 | log_debug("%s failed", cmd)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 117, __func__, "%s failed" , cmd) : -abs(_e); }); | |||
| 118 | return; | |||
| 119 | } | |||
| 120 | log_debug("%s failed with SK=%Xh/ASC=%02Xh/ACQ=%02Xh", cmd, SK(err), ASC(err), ASCQ(err))({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 120, __func__, "%s failed with SK=%Xh/ASC=%02Xh/ACQ=%02Xh" , cmd, (((err) >> 16) & 0xF), (((err) >> 8) & 0xFF), ((err) & 0xFF)) : -abs(_e); }); | |||
| 121 | } | |||
| 122 | ||||
| 123 | struct scsi_cmd { | |||
| 124 | struct cdrom_generic_command cgc; | |||
| 125 | union { | |||
| 126 | struct request_sense s; | |||
| 127 | unsigned char u[18]; | |||
| 128 | } _sense; | |||
| 129 | struct sg_io_hdr sg_io; | |||
| 130 | }; | |||
| 131 | ||||
| 132 | static void scsi_cmd_init(struct udev *udev, struct scsi_cmd *cmd) | |||
| 133 | { | |||
| 134 | memzero(cmd, sizeof(struct scsi_cmd))({ size_t _l_ = (sizeof(struct scsi_cmd)); void *_x_ = (cmd); _l_ == 0 ? _x_ : memset(_x_, 0, _l_); }); | |||
| 135 | cmd->cgc.quiet = 1; | |||
| 136 | cmd->cgc.sense = &cmd->_sense.s; | |||
| 137 | cmd->sg_io.interface_id = 'S'; | |||
| 138 | cmd->sg_io.mx_sb_len = sizeof(cmd->_sense); | |||
| 139 | cmd->sg_io.cmdp = cmd->cgc.cmd; | |||
| 140 | cmd->sg_io.sbp = cmd->_sense.u; | |||
| 141 | cmd->sg_io.flags = SG_FLAG_LUN_INHIBIT2 | SG_FLAG_DIRECT_IO1; | |||
| 142 | } | |||
| 143 | ||||
| 144 | static void scsi_cmd_set(struct udev *udev, struct scsi_cmd *cmd, size_t i, unsigned char arg) | |||
| 145 | { | |||
| 146 | cmd->sg_io.cmd_len = i + 1; | |||
| 147 | cmd->cgc.cmd[i] = arg; | |||
| 148 | } | |||
| 149 | ||||
| 150 | #define CHECK_CONDITION0x01 0x01 | |||
| 151 | ||||
| 152 | static int scsi_cmd_run(struct udev *udev, struct scsi_cmd *cmd, int fd, unsigned char *buf, size_t bufsize) | |||
| 153 | { | |||
| 154 | int ret = 0; | |||
| 155 | ||||
| 156 | if (bufsize > 0) { | |||
| 157 | cmd->sg_io.dxferp = buf; | |||
| 158 | cmd->sg_io.dxfer_len = bufsize; | |||
| 159 | cmd->sg_io.dxfer_direction = SG_DXFER_FROM_DEV-3; | |||
| 160 | } else { | |||
| 161 | cmd->sg_io.dxfer_direction = SG_DXFER_NONE-1; | |||
| 162 | } | |||
| 163 | if (ioctl(fd, SG_IO0x2285, &cmd->sg_io)) | |||
| 164 | return -1; | |||
| 165 | ||||
| 166 | if ((cmd->sg_io.info & SG_INFO_OK_MASK0x1) != SG_INFO_OK0x0) { | |||
| 167 | errno(*__errno_location ()) = EIO5; | |||
| 168 | ret = -1; | |||
| 169 | if (cmd->sg_io.masked_status & CHECK_CONDITION0x01) { | |||
| 170 | ret = ERRCODE(cmd->_sense.u)((((cmd->_sense.u)[2] & 0x0F) << 16) | ((cmd-> _sense.u)[12] << 8) | ((cmd->_sense.u)[13])); | |||
| 171 | if (ret == 0) | |||
| 172 | ret = -1; | |||
| 173 | } | |||
| 174 | } | |||
| 175 | return ret; | |||
| 176 | } | |||
| 177 | ||||
| 178 | static int media_lock(struct udev *udev, int fd, bool_Bool lock) | |||
| 179 | { | |||
| 180 | int err; | |||
| 181 | ||||
| 182 | /* disable the kernel's lock logic */ | |||
| 183 | err = ioctl(fd, CDROM_CLEAR_OPTIONS0x5321, CDO_LOCK0x8); | |||
| 184 | if (err < 0) | |||
| 185 | log_debug("CDROM_CLEAR_OPTIONS, CDO_LOCK failed")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 185, __func__, "CDROM_CLEAR_OPTIONS, CDO_LOCK failed" ) : -abs(_e); }); | |||
| 186 | ||||
| 187 | err = ioctl(fd, CDROM_LOCKDOOR0x5329, lock ? 1 : 0); | |||
| 188 | if (err < 0) | |||
| 189 | log_debug("CDROM_LOCKDOOR failed")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 189, __func__, "CDROM_LOCKDOOR failed" ) : -abs(_e); }); | |||
| 190 | ||||
| 191 | return err; | |||
| 192 | } | |||
| 193 | ||||
| 194 | static int media_eject(struct udev *udev, int fd) | |||
| 195 | { | |||
| 196 | struct scsi_cmd sc; | |||
| 197 | int err; | |||
| 198 | ||||
| 199 | scsi_cmd_init(udev, &sc); | |||
| 200 | scsi_cmd_set(udev, &sc, 0, 0x1b); | |||
| 201 | scsi_cmd_set(udev, &sc, 4, 0x02); | |||
| 202 | scsi_cmd_set(udev, &sc, 5, 0); | |||
| 203 | err = scsi_cmd_run(udev, &sc, fd, NULL((void*)0), 0); | |||
| 204 | if ((err != 0)) { | |||
| 205 | info_scsi_cmd_err(udev, "START_STOP_UNIT", err); | |||
| 206 | return -1; | |||
| 207 | } | |||
| 208 | return 0; | |||
| 209 | } | |||
| 210 | ||||
| 211 | static int cd_capability_compat(struct udev *udev, int fd) | |||
| 212 | { | |||
| 213 | int capability; | |||
| 214 | ||||
| 215 | capability = ioctl(fd, CDROM_GET_CAPABILITY0x5331, NULL((void*)0)); | |||
| 216 | if (capability < 0) { | |||
| 217 | log_debug("CDROM_GET_CAPABILITY failed")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 217, __func__, "CDROM_GET_CAPABILITY failed" ) : -abs(_e); }); | |||
| 218 | return -1; | |||
| 219 | } | |||
| 220 | ||||
| 221 | if (capability & CDC_CD_R0x2000) | |||
| 222 | cd_cd_r = 1; | |||
| 223 | if (capability & CDC_CD_RW0x4000) | |||
| 224 | cd_cd_rw = 1; | |||
| 225 | if (capability & CDC_DVD0x8000) | |||
| 226 | cd_dvd_rom = 1; | |||
| 227 | if (capability & CDC_DVD_R0x10000) | |||
| 228 | cd_dvd_r = 1; | |||
| 229 | if (capability & CDC_DVD_RAM0x20000) | |||
| 230 | cd_dvd_ram = 1; | |||
| 231 | if (capability & CDC_MRW0x80000) | |||
| 232 | cd_mrw = 1; | |||
| 233 | if (capability & CDC_MRW_W0x100000) | |||
| 234 | cd_mrw_w = 1; | |||
| 235 | return 0; | |||
| 236 | } | |||
| 237 | ||||
| 238 | static int cd_media_compat(struct udev *udev, int fd) | |||
| 239 | { | |||
| 240 | if (ioctl(fd, CDROM_DRIVE_STATUS0x5326, CDSL_CURRENT2147483647) != CDS_DISC_OK4) { | |||
| 241 | log_debug("CDROM_DRIVE_STATUS != CDS_DISC_OK")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 241, __func__, "CDROM_DRIVE_STATUS != CDS_DISC_OK" ) : -abs(_e); }); | |||
| 242 | return -1; | |||
| 243 | } | |||
| 244 | cd_media = 1; | |||
| 245 | return 0; | |||
| 246 | } | |||
| 247 | ||||
| 248 | static int cd_inquiry(struct udev *udev, int fd) | |||
| 249 | { | |||
| 250 | struct scsi_cmd sc; | |||
| 251 | unsigned char inq[128]; | |||
| 252 | int err; | |||
| 253 | ||||
| 254 | scsi_cmd_init(udev, &sc); | |||
| 255 | scsi_cmd_set(udev, &sc, 0, 0x12); | |||
| 256 | scsi_cmd_set(udev, &sc, 4, 36); | |||
| 257 | scsi_cmd_set(udev, &sc, 5, 0); | |||
| 258 | err = scsi_cmd_run(udev, &sc, fd, inq, 36); | |||
| 259 | if ((err != 0)) { | |||
| 260 | info_scsi_cmd_err(udev, "INQUIRY", err); | |||
| 261 | return -1; | |||
| 262 | } | |||
| 263 | ||||
| 264 | if ((inq[0] & 0x1F) != 5) { | |||
| 265 | log_debug("not an MMC unit")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 265, __func__, "not an MMC unit" ) : -abs(_e); }); | |||
| 266 | return -1; | |||
| 267 | } | |||
| 268 | ||||
| 269 | log_debug("INQUIRY: [%.8s][%.16s][%.4s]", inq + 8, inq + 16, inq + 32)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 269, __func__, "INQUIRY: [%.8s][%.16s][%.4s]" , inq + 8, inq + 16, inq + 32) : -abs(_e); }); | |||
| 270 | return 0; | |||
| 271 | } | |||
| 272 | ||||
| 273 | static void feature_profile_media(struct udev *udev, int cur_profile) | |||
| 274 | { | |||
| 275 | switch (cur_profile) { | |||
| 276 | case 0x03: | |||
| 277 | case 0x04: | |||
| 278 | case 0x05: | |||
| 279 | log_debug("profile 0x%02x ", cur_profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 279, __func__, "profile 0x%02x " , cur_profile) : -abs(_e); }); | |||
| 280 | cd_media = 1; | |||
| 281 | cd_media_mo = 1; | |||
| 282 | break; | |||
| 283 | case 0x08: | |||
| 284 | log_debug("profile 0x%02x media_cd_rom", cur_profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 284, __func__, "profile 0x%02x media_cd_rom" , cur_profile) : -abs(_e); }); | |||
| 285 | cd_media = 1; | |||
| 286 | cd_media_cd_rom = 1; | |||
| 287 | break; | |||
| 288 | case 0x09: | |||
| 289 | log_debug("profile 0x%02x media_cd_r", cur_profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 289, __func__, "profile 0x%02x media_cd_r" , cur_profile) : -abs(_e); }); | |||
| 290 | cd_media = 1; | |||
| 291 | cd_media_cd_r = 1; | |||
| 292 | break; | |||
| 293 | case 0x0a: | |||
| 294 | log_debug("profile 0x%02x media_cd_rw", cur_profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 294, __func__, "profile 0x%02x media_cd_rw" , cur_profile) : -abs(_e); }); | |||
| 295 | cd_media = 1; | |||
| 296 | cd_media_cd_rw = 1; | |||
| 297 | break; | |||
| 298 | case 0x10: | |||
| 299 | log_debug("profile 0x%02x media_dvd_ro", cur_profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 299, __func__, "profile 0x%02x media_dvd_ro" , cur_profile) : -abs(_e); }); | |||
| 300 | cd_media = 1; | |||
| 301 | cd_media_dvd_rom = 1; | |||
| 302 | break; | |||
| 303 | case 0x11: | |||
| 304 | log_debug("profile 0x%02x media_dvd_r", cur_profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 304, __func__, "profile 0x%02x media_dvd_r" , cur_profile) : -abs(_e); }); | |||
| 305 | cd_media = 1; | |||
| 306 | cd_media_dvd_r = 1; | |||
| 307 | break; | |||
| 308 | case 0x12: | |||
| 309 | log_debug("profile 0x%02x media_dvd_ram", cur_profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 309, __func__, "profile 0x%02x media_dvd_ram" , cur_profile) : -abs(_e); }); | |||
| 310 | cd_media = 1; | |||
| 311 | cd_media_dvd_ram = 1; | |||
| 312 | break; | |||
| 313 | case 0x13: | |||
| 314 | log_debug("profile 0x%02x media_dvd_rw_ro", cur_profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 314, __func__, "profile 0x%02x media_dvd_rw_ro" , cur_profile) : -abs(_e); }); | |||
| 315 | cd_media = 1; | |||
| 316 | cd_media_dvd_rw = 1; | |||
| 317 | cd_media_dvd_rw_ro = 1; | |||
| 318 | break; | |||
| 319 | case 0x14: | |||
| 320 | log_debug("profile 0x%02x media_dvd_rw_seq", cur_profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 320, __func__, "profile 0x%02x media_dvd_rw_seq" , cur_profile) : -abs(_e); }); | |||
| 321 | cd_media = 1; | |||
| 322 | cd_media_dvd_rw = 1; | |||
| 323 | cd_media_dvd_rw_seq = 1; | |||
| 324 | break; | |||
| 325 | case 0x1B: | |||
| 326 | log_debug("profile 0x%02x media_dvd_plus_r", cur_profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 326, __func__, "profile 0x%02x media_dvd_plus_r" , cur_profile) : -abs(_e); }); | |||
| 327 | cd_media = 1; | |||
| 328 | cd_media_dvd_plus_r = 1; | |||
| 329 | break; | |||
| 330 | case 0x1A: | |||
| 331 | log_debug("profile 0x%02x media_dvd_plus_rw", cur_profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 331, __func__, "profile 0x%02x media_dvd_plus_rw" , cur_profile) : -abs(_e); }); | |||
| 332 | cd_media = 1; | |||
| 333 | cd_media_dvd_plus_rw = 1; | |||
| 334 | break; | |||
| 335 | case 0x2A: | |||
| 336 | log_debug("profile 0x%02x media_dvd_plus_rw_dl", cur_profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 336, __func__, "profile 0x%02x media_dvd_plus_rw_dl" , cur_profile) : -abs(_e); }); | |||
| 337 | cd_media = 1; | |||
| 338 | cd_media_dvd_plus_rw_dl = 1; | |||
| 339 | break; | |||
| 340 | case 0x2B: | |||
| 341 | log_debug("profile 0x%02x media_dvd_plus_r_dl", cur_profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 341, __func__, "profile 0x%02x media_dvd_plus_r_dl" , cur_profile) : -abs(_e); }); | |||
| 342 | cd_media = 1; | |||
| 343 | cd_media_dvd_plus_r_dl = 1; | |||
| 344 | break; | |||
| 345 | case 0x40: | |||
| 346 | log_debug("profile 0x%02x media_bd", cur_profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 346, __func__, "profile 0x%02x media_bd" , cur_profile) : -abs(_e); }); | |||
| 347 | cd_media = 1; | |||
| 348 | cd_media_bd = 1; | |||
| 349 | break; | |||
| 350 | case 0x41: | |||
| 351 | case 0x42: | |||
| 352 | log_debug("profile 0x%02x media_bd_r", cur_profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 352, __func__, "profile 0x%02x media_bd_r" , cur_profile) : -abs(_e); }); | |||
| 353 | cd_media = 1; | |||
| 354 | cd_media_bd_r = 1; | |||
| 355 | break; | |||
| 356 | case 0x43: | |||
| 357 | log_debug("profile 0x%02x media_bd_re", cur_profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 357, __func__, "profile 0x%02x media_bd_re" , cur_profile) : -abs(_e); }); | |||
| 358 | cd_media = 1; | |||
| 359 | cd_media_bd_re = 1; | |||
| 360 | break; | |||
| 361 | case 0x50: | |||
| 362 | log_debug("profile 0x%02x media_hddvd", cur_profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 362, __func__, "profile 0x%02x media_hddvd" , cur_profile) : -abs(_e); }); | |||
| 363 | cd_media = 1; | |||
| 364 | cd_media_hddvd = 1; | |||
| 365 | break; | |||
| 366 | case 0x51: | |||
| 367 | log_debug("profile 0x%02x media_hddvd_r", cur_profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 367, __func__, "profile 0x%02x media_hddvd_r" , cur_profile) : -abs(_e); }); | |||
| 368 | cd_media = 1; | |||
| 369 | cd_media_hddvd_r = 1; | |||
| 370 | break; | |||
| 371 | case 0x52: | |||
| 372 | log_debug("profile 0x%02x media_hddvd_rw", cur_profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 372, __func__, "profile 0x%02x media_hddvd_rw" , cur_profile) : -abs(_e); }); | |||
| 373 | cd_media = 1; | |||
| 374 | cd_media_hddvd_rw = 1; | |||
| 375 | break; | |||
| 376 | default: | |||
| 377 | log_debug("profile 0x%02x <ignored>", cur_profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 377, __func__, "profile 0x%02x <ignored>" , cur_profile) : -abs(_e); }); | |||
| 378 | break; | |||
| 379 | } | |||
| 380 | } | |||
| 381 | ||||
| 382 | static int feature_profiles(struct udev *udev, const unsigned char *profiles, size_t size) | |||
| 383 | { | |||
| 384 | unsigned int i; | |||
| 385 | ||||
| 386 | for (i = 0; i+4 <= size; i += 4) { | |||
| 387 | int profile; | |||
| 388 | ||||
| 389 | profile = profiles[i] << 8 | profiles[i+1]; | |||
| 390 | switch (profile) { | |||
| 391 | case 0x03: | |||
| 392 | case 0x04: | |||
| 393 | case 0x05: | |||
| 394 | log_debug("profile 0x%02x mo", profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 394, __func__, "profile 0x%02x mo" , profile) : -abs(_e); }); | |||
| 395 | cd_mo = 1; | |||
| 396 | break; | |||
| 397 | case 0x08: | |||
| 398 | log_debug("profile 0x%02x cd_rom", profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 398, __func__, "profile 0x%02x cd_rom" , profile) : -abs(_e); }); | |||
| 399 | cd_cd_rom = 1; | |||
| 400 | break; | |||
| 401 | case 0x09: | |||
| 402 | log_debug("profile 0x%02x cd_r", profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 402, __func__, "profile 0x%02x cd_r" , profile) : -abs(_e); }); | |||
| 403 | cd_cd_r = 1; | |||
| 404 | break; | |||
| 405 | case 0x0A: | |||
| 406 | log_debug("profile 0x%02x cd_rw", profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 406, __func__, "profile 0x%02x cd_rw" , profile) : -abs(_e); }); | |||
| 407 | cd_cd_rw = 1; | |||
| 408 | break; | |||
| 409 | case 0x10: | |||
| 410 | log_debug("profile 0x%02x dvd_rom", profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 410, __func__, "profile 0x%02x dvd_rom" , profile) : -abs(_e); }); | |||
| 411 | cd_dvd_rom = 1; | |||
| 412 | break; | |||
| 413 | case 0x12: | |||
| 414 | log_debug("profile 0x%02x dvd_ram", profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 414, __func__, "profile 0x%02x dvd_ram" , profile) : -abs(_e); }); | |||
| 415 | cd_dvd_ram = 1; | |||
| 416 | break; | |||
| 417 | case 0x13: | |||
| 418 | case 0x14: | |||
| 419 | log_debug("profile 0x%02x dvd_rw", profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 419, __func__, "profile 0x%02x dvd_rw" , profile) : -abs(_e); }); | |||
| 420 | cd_dvd_rw = 1; | |||
| 421 | break; | |||
| 422 | case 0x1B: | |||
| 423 | log_debug("profile 0x%02x dvd_plus_r", profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 423, __func__, "profile 0x%02x dvd_plus_r" , profile) : -abs(_e); }); | |||
| 424 | cd_dvd_plus_r = 1; | |||
| 425 | break; | |||
| 426 | case 0x1A: | |||
| 427 | log_debug("profile 0x%02x dvd_plus_rw", profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 427, __func__, "profile 0x%02x dvd_plus_rw" , profile) : -abs(_e); }); | |||
| 428 | cd_dvd_plus_rw = 1; | |||
| 429 | break; | |||
| 430 | case 0x2A: | |||
| 431 | log_debug("profile 0x%02x dvd_plus_rw_dl", profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 431, __func__, "profile 0x%02x dvd_plus_rw_dl" , profile) : -abs(_e); }); | |||
| 432 | cd_dvd_plus_rw_dl = 1; | |||
| 433 | break; | |||
| 434 | case 0x2B: | |||
| 435 | log_debug("profile 0x%02x dvd_plus_r_dl", profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 435, __func__, "profile 0x%02x dvd_plus_r_dl" , profile) : -abs(_e); }); | |||
| 436 | cd_dvd_plus_r_dl = 1; | |||
| 437 | break; | |||
| 438 | case 0x40: | |||
| 439 | cd_bd = 1; | |||
| 440 | log_debug("profile 0x%02x bd", profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 440, __func__, "profile 0x%02x bd" , profile) : -abs(_e); }); | |||
| 441 | break; | |||
| 442 | case 0x41: | |||
| 443 | case 0x42: | |||
| 444 | cd_bd_r = 1; | |||
| 445 | log_debug("profile 0x%02x bd_r", profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 445, __func__, "profile 0x%02x bd_r" , profile) : -abs(_e); }); | |||
| 446 | break; | |||
| 447 | case 0x43: | |||
| 448 | cd_bd_re = 1; | |||
| 449 | log_debug("profile 0x%02x bd_re", profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 449, __func__, "profile 0x%02x bd_re" , profile) : -abs(_e); }); | |||
| 450 | break; | |||
| 451 | case 0x50: | |||
| 452 | cd_hddvd = 1; | |||
| 453 | log_debug("profile 0x%02x hddvd", profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 453, __func__, "profile 0x%02x hddvd" , profile) : -abs(_e); }); | |||
| 454 | break; | |||
| 455 | case 0x51: | |||
| 456 | cd_hddvd_r = 1; | |||
| 457 | log_debug("profile 0x%02x hddvd_r", profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 457, __func__, "profile 0x%02x hddvd_r" , profile) : -abs(_e); }); | |||
| 458 | break; | |||
| 459 | case 0x52: | |||
| 460 | cd_hddvd_rw = 1; | |||
| 461 | log_debug("profile 0x%02x hddvd_rw", profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 461, __func__, "profile 0x%02x hddvd_rw" , profile) : -abs(_e); }); | |||
| 462 | break; | |||
| 463 | default: | |||
| 464 | log_debug("profile 0x%02x <ignored>", profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 464, __func__, "profile 0x%02x <ignored>" , profile) : -abs(_e); }); | |||
| 465 | break; | |||
| 466 | } | |||
| 467 | } | |||
| 468 | return 0; | |||
| 469 | } | |||
| 470 | ||||
| 471 | /* returns 0 if media was detected */ | |||
| 472 | static int cd_profiles_old_mmc(struct udev *udev, int fd) | |||
| 473 | { | |||
| 474 | struct scsi_cmd sc; | |||
| 475 | int err; | |||
| 476 | ||||
| 477 | unsigned char header[32]; | |||
| 478 | ||||
| 479 | scsi_cmd_init(udev, &sc); | |||
| 480 | scsi_cmd_set(udev, &sc, 0, 0x51); | |||
| 481 | scsi_cmd_set(udev, &sc, 8, sizeof(header)); | |||
| 482 | scsi_cmd_set(udev, &sc, 9, 0); | |||
| 483 | err = scsi_cmd_run(udev, &sc, fd, header, sizeof(header)); | |||
| 484 | if ((err != 0)) { | |||
| 485 | info_scsi_cmd_err(udev, "READ DISC INFORMATION", err); | |||
| 486 | if (cd_media == 1) { | |||
| 487 | log_debug("no current profile, but disc is present; assuming CD-ROM")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 487, __func__, "no current profile, but disc is present; assuming CD-ROM" ) : -abs(_e); }); | |||
| 488 | cd_media_cd_rom = 1; | |||
| 489 | cd_media_track_count = 1; | |||
| 490 | cd_media_track_count_data = 1; | |||
| 491 | return 0; | |||
| 492 | } else { | |||
| 493 | log_debug("no current profile, assuming no media")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 493, __func__, "no current profile, assuming no media" ) : -abs(_e); }); | |||
| 494 | return -1; | |||
| 495 | } | |||
| 496 | }; | |||
| 497 | ||||
| 498 | cd_media = 1; | |||
| 499 | ||||
| 500 | if (header[2] & 16) { | |||
| 501 | cd_media_cd_rw = 1; | |||
| 502 | log_debug("profile 0x0a media_cd_rw")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 502, __func__, "profile 0x0a media_cd_rw" ) : -abs(_e); }); | |||
| 503 | } else if ((header[2] & 3) < 2 && cd_cd_r) { | |||
| 504 | cd_media_cd_r = 1; | |||
| 505 | log_debug("profile 0x09 media_cd_r")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 505, __func__, "profile 0x09 media_cd_r" ) : -abs(_e); }); | |||
| 506 | } else { | |||
| 507 | cd_media_cd_rom = 1; | |||
| 508 | log_debug("profile 0x08 media_cd_rom")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 508, __func__, "profile 0x08 media_cd_rom" ) : -abs(_e); }); | |||
| 509 | } | |||
| 510 | return 0; | |||
| 511 | } | |||
| 512 | ||||
| 513 | /* returns 0 if media was detected */ | |||
| 514 | static int cd_profiles(struct udev *udev, int fd) | |||
| 515 | { | |||
| 516 | struct scsi_cmd sc; | |||
| 517 | unsigned char features[65530]; | |||
| 518 | unsigned int cur_profile = 0; | |||
| 519 | unsigned int len; | |||
| 520 | unsigned int i; | |||
| 521 | int err; | |||
| 522 | int ret; | |||
| 523 | ||||
| 524 | ret = -1; | |||
| 525 | ||||
| 526 | /* First query the current profile */ | |||
| 527 | scsi_cmd_init(udev, &sc); | |||
| 528 | scsi_cmd_set(udev, &sc, 0, 0x46); | |||
| 529 | scsi_cmd_set(udev, &sc, 8, 8); | |||
| 530 | scsi_cmd_set(udev, &sc, 9, 0); | |||
| 531 | err = scsi_cmd_run(udev, &sc, fd, features, 8); | |||
| 532 | if ((err != 0)) { | |||
| 533 | info_scsi_cmd_err(udev, "GET CONFIGURATION", err); | |||
| 534 | /* handle pre-MMC2 drives which do not support GET CONFIGURATION */ | |||
| 535 | if (SK(err)(((err) >> 16) & 0xF) == 0x5 && IN_SET(ASC(err), 0x20, 0x24)({ _Bool _found = 0; static __attribute__ ((unused)) char _static_assert__macros_need_to_be_extended [20 - sizeof((int[]){0x20, 0x24})/sizeof(int)]; switch((((err ) >> 8) & 0xFF)) { case 0x20: case 0x24: _found = 1 ; break; default: break; } _found; })) { | |||
| 536 | log_debug("drive is pre-MMC2 and does not support 46h get configuration command")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 536, __func__, "drive is pre-MMC2 and does not support 46h get configuration command" ) : -abs(_e); }); | |||
| 537 | log_debug("trying to work around the problem")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 537, __func__, "trying to work around the problem" ) : -abs(_e); }); | |||
| 538 | ret = cd_profiles_old_mmc(udev, fd); | |||
| 539 | } | |||
| 540 | goto out; | |||
| 541 | } | |||
| 542 | ||||
| 543 | cur_profile = features[6] << 8 | features[7]; | |||
| 544 | if (cur_profile > 0) { | |||
| 545 | log_debug("current profile 0x%02x", cur_profile)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 545, __func__, "current profile 0x%02x" , cur_profile) : -abs(_e); }); | |||
| 546 | feature_profile_media (udev, cur_profile); | |||
| 547 | ret = 0; /* we have media */ | |||
| 548 | } else { | |||
| 549 | log_debug("no current profile, assuming no media")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 549, __func__, "no current profile, assuming no media" ) : -abs(_e); }); | |||
| 550 | } | |||
| 551 | ||||
| 552 | len = features[0] << 24 | features[1] << 16 | features[2] << 8 | features[3]; | |||
| 553 | log_debug("GET CONFIGURATION: size of features buffer 0x%04x", len)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 553, __func__, "GET CONFIGURATION: size of features buffer 0x%04x" , len) : -abs(_e); }); | |||
| 554 | ||||
| 555 | if (len > sizeof(features)) { | |||
| 556 | log_debug("cannot get features in a single query, truncating")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 556, __func__, "cannot get features in a single query, truncating" ) : -abs(_e); }); | |||
| 557 | len = sizeof(features); | |||
| 558 | } else if (len <= 8) | |||
| 559 | len = sizeof(features); | |||
| 560 | ||||
| 561 | /* Now get the full feature buffer */ | |||
| 562 | scsi_cmd_init(udev, &sc); | |||
| 563 | scsi_cmd_set(udev, &sc, 0, 0x46); | |||
| 564 | scsi_cmd_set(udev, &sc, 7, ( len >> 8 ) & 0xff); | |||
| 565 | scsi_cmd_set(udev, &sc, 8, len & 0xff); | |||
| 566 | scsi_cmd_set(udev, &sc, 9, 0); | |||
| 567 | err = scsi_cmd_run(udev, &sc, fd, features, len); | |||
| 568 | if ((err != 0)) { | |||
| 569 | info_scsi_cmd_err(udev, "GET CONFIGURATION", err); | |||
| 570 | return -1; | |||
| 571 | } | |||
| 572 | ||||
| 573 | /* parse the length once more, in case the drive decided to have other features suddenly :) */ | |||
| 574 | len = features[0] << 24 | features[1] << 16 | features[2] << 8 | features[3]; | |||
| 575 | log_debug("GET CONFIGURATION: size of features buffer 0x%04x", len)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 575, __func__, "GET CONFIGURATION: size of features buffer 0x%04x" , len) : -abs(_e); }); | |||
| 576 | ||||
| 577 | if (len > sizeof(features)) { | |||
| 578 | log_debug("cannot get features in a single query, truncating")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 578, __func__, "cannot get features in a single query, truncating" ) : -abs(_e); }); | |||
| 579 | len = sizeof(features); | |||
| 580 | } | |||
| 581 | ||||
| 582 | /* device features */ | |||
| 583 | for (i = 8; i+4 < len; i += (4 + features[i+3])) { | |||
| 584 | unsigned int feature; | |||
| 585 | ||||
| 586 | feature = features[i] << 8 | features[i+1]; | |||
| 587 | ||||
| 588 | switch (feature) { | |||
| 589 | case 0x00: | |||
| 590 | log_debug("GET CONFIGURATION: feature 'profiles', with %i entries", features[i+3] / 4)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 590, __func__, "GET CONFIGURATION: feature 'profiles', with %i entries" , features[i+3] / 4) : -abs(_e); }); | |||
| 591 | feature_profiles(udev, &features[i]+4, MIN(features[i+3], len - i - 4)__extension__ ({ const typeof((features[i+3])) __unique_prefix_A2 = ((features[i+3])); const typeof((len - i - 4)) __unique_prefix_B3 = ((len - i - 4)); __unique_prefix_A2 < __unique_prefix_B3 ? __unique_prefix_A2 : __unique_prefix_B3; })); | |||
| 592 | break; | |||
| 593 | default: | |||
| 594 | log_debug("GET CONFIGURATION: feature 0x%04x <ignored>, with 0x%02x bytes", feature, features[i+3])({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 594, __func__, "GET CONFIGURATION: feature 0x%04x <ignored>, with 0x%02x bytes" , feature, features[i+3]) : -abs(_e); }); | |||
| 595 | break; | |||
| 596 | } | |||
| 597 | } | |||
| 598 | out: | |||
| 599 | return ret; | |||
| 600 | } | |||
| 601 | ||||
| 602 | static int cd_media_info(struct udev *udev, int fd) | |||
| 603 | { | |||
| 604 | struct scsi_cmd sc; | |||
| 605 | unsigned char header[32]; | |||
| 606 | static const char *media_status[] = { | |||
| 607 | "blank", | |||
| 608 | "appendable", | |||
| 609 | "complete", | |||
| 610 | "other" | |||
| 611 | }; | |||
| 612 | int err; | |||
| 613 | ||||
| 614 | scsi_cmd_init(udev, &sc); | |||
| 615 | scsi_cmd_set(udev, &sc, 0, 0x51); | |||
| 616 | scsi_cmd_set(udev, &sc, 8, sizeof(header) & 0xff); | |||
| 617 | scsi_cmd_set(udev, &sc, 9, 0); | |||
| 618 | err = scsi_cmd_run(udev, &sc, fd, header, sizeof(header)); | |||
| 619 | if ((err != 0)) { | |||
| 620 | info_scsi_cmd_err(udev, "READ DISC INFORMATION", err); | |||
| 621 | return -1; | |||
| 622 | }; | |||
| 623 | ||||
| 624 | cd_media = 1; | |||
| 625 | log_debug("disk type %02x", header[8])({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 625, __func__, "disk type %02x" , header[8]) : -abs(_e); }); | |||
| 626 | log_debug("hardware reported media status: %s", media_status[header[2] & 3])({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 626, __func__, "hardware reported media status: %s" , media_status[header[2] & 3]) : -abs(_e); }); | |||
| 627 | ||||
| 628 | /* exclude plain CDROM, some fake cdroms return 0 for "blank" media here */ | |||
| 629 | if (!cd_media_cd_rom) | |||
| 630 | cd_media_state = media_status[header[2] & 3]; | |||
| 631 | ||||
| 632 | /* fresh DVD-RW in restricted overwite mode reports itself as | |||
| 633 | * "appendable"; change it to "blank" to make it consistent with what | |||
| 634 | * gets reported after blanking, and what userspace expects */ | |||
| 635 | if (cd_media_dvd_rw_ro && (header[2] & 3) == 1) | |||
| 636 | cd_media_state = media_status[0]; | |||
| 637 | ||||
| 638 | /* DVD+RW discs (and DVD-RW in restricted mode) once formatted are | |||
| 639 | * always "complete", DVD-RAM are "other" or "complete" if the disc is | |||
| 640 | * write protected; we need to check the contents if it is blank */ | |||
| 641 | 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) { | |||
| 642 | unsigned char buffer[32 * 2048]; | |||
| 643 | unsigned char len; | |||
| 644 | int offset; | |||
| 645 | ||||
| 646 | if (cd_media_dvd_ram) { | |||
| 647 | /* a write protected dvd-ram may report "complete" status */ | |||
| 648 | ||||
| 649 | unsigned char dvdstruct[8]; | |||
| 650 | unsigned char format[12]; | |||
| 651 | ||||
| 652 | scsi_cmd_init(udev, &sc); | |||
| 653 | scsi_cmd_set(udev, &sc, 0, 0xAD); | |||
| 654 | scsi_cmd_set(udev, &sc, 7, 0xC0); | |||
| 655 | scsi_cmd_set(udev, &sc, 9, sizeof(dvdstruct)); | |||
| 656 | scsi_cmd_set(udev, &sc, 11, 0); | |||
| 657 | err = scsi_cmd_run(udev, &sc, fd, dvdstruct, sizeof(dvdstruct)); | |||
| 658 | if ((err != 0)) { | |||
| 659 | info_scsi_cmd_err(udev, "READ DVD STRUCTURE", err); | |||
| 660 | return -1; | |||
| 661 | } | |||
| 662 | if (dvdstruct[4] & 0x02) { | |||
| 663 | cd_media_state = media_status[2]; | |||
| 664 | log_debug("write-protected DVD-RAM media inserted")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 664, __func__, "write-protected DVD-RAM media inserted" ) : -abs(_e); }); | |||
| 665 | goto determined; | |||
| 666 | } | |||
| 667 | ||||
| 668 | /* let's make sure we don't try to read unformatted media */ | |||
| 669 | scsi_cmd_init(udev, &sc); | |||
| 670 | scsi_cmd_set(udev, &sc, 0, 0x23); | |||
| 671 | scsi_cmd_set(udev, &sc, 8, sizeof(format)); | |||
| 672 | scsi_cmd_set(udev, &sc, 9, 0); | |||
| 673 | err = scsi_cmd_run(udev, &sc, fd, format, sizeof(format)); | |||
| 674 | if ((err != 0)) { | |||
| 675 | info_scsi_cmd_err(udev, "READ DVD FORMAT CAPACITIES", err); | |||
| 676 | return -1; | |||
| 677 | } | |||
| 678 | ||||
| 679 | len = format[3]; | |||
| 680 | if (len & 7 || len < 16) { | |||
| 681 | log_debug("invalid format capacities length")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 681, __func__, "invalid format capacities length" ) : -abs(_e); }); | |||
| 682 | return -1; | |||
| 683 | } | |||
| 684 | ||||
| 685 | switch(format[8] & 3) { | |||
| 686 | case 1: | |||
| 687 | log_debug("unformatted DVD-RAM media inserted")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 687, __func__, "unformatted DVD-RAM media inserted" ) : -abs(_e); }); | |||
| 688 | /* This means that last format was interrupted | |||
| 689 | * or failed, blank dvd-ram discs are factory | |||
| 690 | * formatted. Take no action here as it takes | |||
| 691 | * quite a while to reformat a dvd-ram and it's | |||
| 692 | * not automatically started */ | |||
| 693 | goto determined; | |||
| 694 | ||||
| 695 | case 2: | |||
| 696 | log_debug("formatted DVD-RAM media inserted")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 696, __func__, "formatted DVD-RAM media inserted" ) : -abs(_e); }); | |||
| 697 | break; | |||
| 698 | ||||
| 699 | case 3: | |||
| 700 | cd_media = 0; //return no media | |||
| 701 | log_debug("format capacities returned no media")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 701, __func__, "format capacities returned no media" ) : -abs(_e); }); | |||
| 702 | return -1; | |||
| 703 | } | |||
| 704 | } | |||
| 705 | ||||
| 706 | /* Take a closer look at formatted media (unformatted DVD+RW | |||
| 707 | * has "blank" status", DVD-RAM was examined earlier) and check | |||
| 708 | * for ISO and UDF PVDs or a fs superblock presence and do it | |||
| 709 | * in one ioctl (we need just sectors 0 and 16) */ | |||
| 710 | scsi_cmd_init(udev, &sc); | |||
| 711 | scsi_cmd_set(udev, &sc, 0, 0x28); | |||
| 712 | scsi_cmd_set(udev, &sc, 5, 0); | |||
| 713 | scsi_cmd_set(udev, &sc, 8, 32); | |||
| 714 | scsi_cmd_set(udev, &sc, 9, 0); | |||
| 715 | err = scsi_cmd_run(udev, &sc, fd, buffer, sizeof(buffer)); | |||
| 716 | if ((err != 0)) { | |||
| 717 | cd_media = 0; | |||
| 718 | info_scsi_cmd_err(udev, "READ FIRST 32 BLOCKS", err); | |||
| 719 | return -1; | |||
| 720 | } | |||
| 721 | ||||
| 722 | /* if any non-zero data is found in sector 16 (iso and udf) or | |||
| 723 | * eventually 0 (fat32 boot sector, ext2 superblock, etc), disc | |||
| 724 | * is assumed non-blank */ | |||
| 725 | ||||
| 726 | for (offset = 32768; offset < (32768 + 2048); offset++) { | |||
| 727 | if (buffer [offset]) { | |||
| 728 | log_debug("data in block 16, assuming complete")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 728, __func__, "data in block 16, assuming complete" ) : -abs(_e); }); | |||
| 729 | goto determined; | |||
| 730 | } | |||
| 731 | } | |||
| 732 | ||||
| 733 | for (offset = 0; offset < 2048; offset++) { | |||
| 734 | if (buffer [offset]) { | |||
| 735 | log_debug("data in block 0, assuming complete")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 735, __func__, "data in block 0, assuming complete" ) : -abs(_e); }); | |||
| 736 | goto determined; | |||
| 737 | } | |||
| 738 | } | |||
| 739 | ||||
| 740 | cd_media_state = media_status[0]; | |||
| 741 | log_debug("no data in blocks 0 or 16, assuming blank")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 741, __func__, "no data in blocks 0 or 16, assuming blank" ) : -abs(_e); }); | |||
| 742 | } | |||
| 743 | ||||
| 744 | determined: | |||
| 745 | /* "other" is e. g. DVD-RAM, can't append sessions there; DVDs in | |||
| 746 | * restricted overwrite mode can never append, only in sequential mode */ | |||
| 747 | if ((header[2] & 3) < 2 && !cd_media_dvd_rw_ro) | |||
| 748 | cd_media_session_next = header[10] << 8 | header[5]; | |||
| 749 | cd_media_session_count = header[9] << 8 | header[4]; | |||
| 750 | cd_media_track_count = header[11] << 8 | header[6]; | |||
| 751 | ||||
| 752 | return 0; | |||
| 753 | } | |||
| 754 | ||||
| 755 | static int cd_media_toc(struct udev *udev, int fd) | |||
| 756 | { | |||
| 757 | struct scsi_cmd sc; | |||
| 758 | unsigned char header[12]; | |||
| 759 | unsigned char toc[65536]; | |||
| 760 | unsigned int len, i, num_tracks; | |||
| 761 | unsigned char *p; | |||
| 762 | int err; | |||
| 763 | ||||
| 764 | scsi_cmd_init(udev, &sc); | |||
| 765 | scsi_cmd_set(udev, &sc, 0, 0x43); | |||
| 766 | scsi_cmd_set(udev, &sc, 6, 1); | |||
| 767 | scsi_cmd_set(udev, &sc, 8, sizeof(header) & 0xff); | |||
| 768 | scsi_cmd_set(udev, &sc, 9, 0); | |||
| 769 | err = scsi_cmd_run(udev, &sc, fd, header, sizeof(header)); | |||
| 770 | if ((err
| |||
| 771 | info_scsi_cmd_err(udev, "READ TOC", err); | |||
| 772 | return -1; | |||
| 773 | } | |||
| 774 | ||||
| 775 | len = (header[0] << 8 | header[1]) + 2; | |||
| 776 | log_debug("READ TOC: len: %d, start track: %d, end track: %d", len, header[2], header[3])({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 776, __func__, "READ TOC: len: %d, start track: %d, end track: %d" , len, header[2], header[3]) : -abs(_e); }); | |||
| 777 | if (len > sizeof(toc)) | |||
| 778 | return -1; | |||
| 779 | if (len < 2) | |||
| 780 | return -1; | |||
| 781 | /* 2: first track, 3: last track */ | |||
| 782 | num_tracks = header[3] - header[2] + 1; | |||
| 783 | ||||
| 784 | /* empty media has no tracks */ | |||
| 785 | if (len < 8) | |||
| 786 | return 0; | |||
| 787 | ||||
| 788 | scsi_cmd_init(udev, &sc); | |||
| 789 | scsi_cmd_set(udev, &sc, 0, 0x43); | |||
| 790 | scsi_cmd_set(udev, &sc, 6, header[2]); /* First Track/Session Number */ | |||
| 791 | scsi_cmd_set(udev, &sc, 7, (len >> 8) & 0xff); | |||
| 792 | scsi_cmd_set(udev, &sc, 8, len & 0xff); | |||
| 793 | scsi_cmd_set(udev, &sc, 9, 0); | |||
| 794 | err = scsi_cmd_run(udev, &sc, fd, toc, len); | |||
| 795 | if ((err
| |||
| 796 | info_scsi_cmd_err(udev, "READ TOC (tracks)", err); | |||
| 797 | return -1; | |||
| 798 | } | |||
| 799 | ||||
| 800 | /* Take care to not iterate beyond the last valid track as specified in | |||
| 801 | * the TOC, but also avoid going beyond the TOC length, just in case | |||
| 802 | * the last track number is invalidly large */ | |||
| 803 | for (p = toc+4, i = 4; i < len-8 && num_tracks > 0; i += 8, p += 8, --num_tracks) { | |||
| 804 | unsigned int block; | |||
| 805 | unsigned int is_data_track; | |||
| 806 | ||||
| 807 | is_data_track = (p[1] & 0x04) != 0; | |||
| ||||
| 808 | ||||
| 809 | block = p[4] << 24 | p[5] << 16 | p[6] << 8 | p[7]; | |||
| 810 | log_debug("track=%u info=0x%x(%s) start_block=%u",({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 811, __func__, "track=%u info=0x%x(%s) start_block=%u" , p[2], p[1] & 0x0f, is_data_track ? "data":"audio", block ) : -abs(_e); }) | |||
| 811 | p[2], p[1] & 0x0f, is_data_track ? "data":"audio", block)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 811, __func__, "track=%u info=0x%x(%s) start_block=%u" , p[2], p[1] & 0x0f, is_data_track ? "data":"audio", block ) : -abs(_e); }); | |||
| 812 | ||||
| 813 | if (is_data_track) | |||
| 814 | cd_media_track_count_data++; | |||
| 815 | else | |||
| 816 | cd_media_track_count_audio++; | |||
| 817 | } | |||
| 818 | ||||
| 819 | scsi_cmd_init(udev, &sc); | |||
| 820 | scsi_cmd_set(udev, &sc, 0, 0x43); | |||
| 821 | scsi_cmd_set(udev, &sc, 2, 1); /* Session Info */ | |||
| 822 | scsi_cmd_set(udev, &sc, 8, sizeof(header)); | |||
| 823 | scsi_cmd_set(udev, &sc, 9, 0); | |||
| 824 | err = scsi_cmd_run(udev, &sc, fd, header, sizeof(header)); | |||
| 825 | if ((err != 0)) { | |||
| 826 | info_scsi_cmd_err(udev, "READ TOC (multi session)", err); | |||
| 827 | return -1; | |||
| 828 | } | |||
| 829 | len = header[4+4] << 24 | header[4+5] << 16 | header[4+6] << 8 | header[4+7]; | |||
| 830 | log_debug("last track %u starts at block %u", header[4+2], len)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 830, __func__, "last track %u starts at block %u" , header[4+2], len) : -abs(_e); }); | |||
| 831 | cd_media_session_last_offset = (unsigned long long int)len * 2048; | |||
| 832 | return 0; | |||
| 833 | } | |||
| 834 | ||||
| 835 | int main(int argc, char *argv[]) { | |||
| 836 | struct udev *udev; | |||
| 837 | static const struct option options[] = { | |||
| 838 | { "lock-media", no_argument0, NULL((void*)0), 'l' }, | |||
| 839 | { "unlock-media", no_argument0, NULL((void*)0), 'u' }, | |||
| 840 | { "eject-media", no_argument0, NULL((void*)0), 'e' }, | |||
| 841 | { "debug", no_argument0, NULL((void*)0), 'd' }, | |||
| 842 | { "help", no_argument0, NULL((void*)0), 'h' }, | |||
| 843 | {} | |||
| 844 | }; | |||
| 845 | bool_Bool eject = false0; | |||
| 846 | bool_Bool lock = false0; | |||
| 847 | bool_Bool unlock = false0; | |||
| 848 | const char *node = NULL((void*)0); | |||
| 849 | int fd = -1; | |||
| 850 | int cnt; | |||
| 851 | int rc = 0; | |||
| 852 | ||||
| 853 | log_set_target(LOG_TARGET_AUTO); | |||
| 854 | udev_parse_config(); | |||
| 855 | log_parse_environment()log_parse_environment_realm(LOG_REALM_UDEV); | |||
| 856 | log_open(); | |||
| 857 | ||||
| 858 | udev = udev_new(); | |||
| 859 | if (udev == NULL((void*)0)) | |||
| ||||
| 860 | goto exit; | |||
| 861 | ||||
| 862 | for (;;) { | |||
| 863 | int option; | |||
| 864 | ||||
| 865 | option = getopt_long(argc, argv, "deluh", options, NULL((void*)0)); | |||
| 866 | if (option == -1) | |||
| 867 | break; | |||
| 868 | ||||
| 869 | switch (option) { | |||
| 870 | case 'l': | |||
| 871 | lock = true1; | |||
| 872 | break; | |||
| 873 | case 'u': | |||
| 874 | unlock = true1; | |||
| 875 | break; | |||
| 876 | case 'e': | |||
| 877 | eject = true1; | |||
| 878 | break; | |||
| 879 | case 'd': | |||
| 880 | log_set_target(LOG_TARGET_CONSOLE); | |||
| 881 | log_set_max_level(LOG_DEBUG)log_set_max_level_realm(LOG_REALM_UDEV, (7)); | |||
| 882 | log_open(); | |||
| 883 | break; | |||
| 884 | case 'h': | |||
| 885 | printf("Usage: cdrom_id [options] <device>\n" | |||
| 886 | " -l,--lock-media lock the media (to enable eject request events)\n" | |||
| 887 | " -u,--unlock-media unlock the media\n" | |||
| 888 | " -e,--eject-media eject the media\n" | |||
| 889 | " -d,--debug debug to stderr\n" | |||
| 890 | " -h,--help print this help text\n\n"); | |||
| 891 | goto exit; | |||
| 892 | default: | |||
| 893 | rc = 1; | |||
| 894 | goto exit; | |||
| 895 | } | |||
| 896 | } | |||
| 897 | ||||
| 898 | node = argv[optind]; | |||
| 899 | if (!node) { | |||
| 900 | log_error("no device")({ int _level = (((3))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 900, __func__, "no device" ) : -abs(_e); }); | |||
| 901 | fprintf(stderrstderr, "no device\n"); | |||
| 902 | rc = 1; | |||
| 903 | goto exit; | |||
| 904 | } | |||
| 905 | ||||
| 906 | initialize_srand(); | |||
| 907 | for (cnt = 20; cnt > 0; cnt--) { | |||
| 908 | struct timespec duration; | |||
| 909 | ||||
| 910 | fd = open(node, O_RDONLY00|O_NONBLOCK04000|O_CLOEXEC02000000|(is_mounted(node) ? 0 : O_EXCL0200)); | |||
| 911 | if (fd >= 0 || errno(*__errno_location ()) != EBUSY16) | |||
| 912 | break; | |||
| 913 | duration.tv_sec = 0; | |||
| 914 | duration.tv_nsec = (100 * 1000 * 1000) + (rand() % 100 * 1000 * 1000); | |||
| 915 | nanosleep(&duration, NULL((void*)0)); | |||
| 916 | } | |||
| 917 | if (fd
| |||
| 918 | log_debug("unable to open '%s'", node)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 918, __func__, "unable to open '%s'" , node) : -abs(_e); }); | |||
| 919 | fprintf(stderrstderr, "unable to open '%s'\n", node); | |||
| 920 | rc = 1; | |||
| 921 | goto exit; | |||
| 922 | } | |||
| 923 | log_debug("probing: '%s'", node)({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 923, __func__, "probing: '%s'" , node) : -abs(_e); }); | |||
| 924 | ||||
| 925 | /* same data as original cdrom_id */ | |||
| 926 | if (cd_capability_compat(udev, fd) < 0) { | |||
| 927 | rc = 1; | |||
| 928 | goto exit; | |||
| 929 | } | |||
| 930 | ||||
| 931 | /* check for media - don't bail if there's no media as we still need to | |||
| 932 | * to read profiles */ | |||
| 933 | cd_media_compat(udev, fd); | |||
| 934 | ||||
| 935 | /* check if drive talks MMC */ | |||
| 936 | if (cd_inquiry(udev, fd) < 0) | |||
| 937 | goto work; | |||
| 938 | ||||
| 939 | /* read drive and possibly current profile */ | |||
| 940 | if (cd_profiles(udev, fd) != 0) | |||
| 941 | goto work; | |||
| 942 | ||||
| 943 | /* at this point we are guaranteed to have media in the drive - find out more about it */ | |||
| 944 | ||||
| 945 | /* get session/track info */ | |||
| 946 | cd_media_toc(udev, fd); | |||
| 947 | ||||
| 948 | /* get writable media state */ | |||
| 949 | cd_media_info(udev, fd); | |||
| 950 | ||||
| 951 | work: | |||
| 952 | /* lock the media, so we enable eject button events */ | |||
| 953 | if (lock && cd_media) { | |||
| 954 | log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (lock)")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 954, __func__, "PREVENT_ALLOW_MEDIUM_REMOVAL (lock)" ) : -abs(_e); }); | |||
| 955 | media_lock(udev, fd, true1); | |||
| 956 | } | |||
| 957 | ||||
| 958 | if (unlock && cd_media) { | |||
| 959 | log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (unlock)")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 959, __func__, "PREVENT_ALLOW_MEDIUM_REMOVAL (unlock)" ) : -abs(_e); }); | |||
| 960 | media_lock(udev, fd, false0); | |||
| 961 | } | |||
| 962 | ||||
| 963 | if (eject) { | |||
| 964 | log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (unlock)")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 964, __func__, "PREVENT_ALLOW_MEDIUM_REMOVAL (unlock)" ) : -abs(_e); }); | |||
| 965 | media_lock(udev, fd, false0); | |||
| 966 | log_debug("START_STOP_UNIT (eject)")({ int _level = (((7))), _e = ((0)), _realm = (LOG_REALM_UDEV ); (log_get_max_level_realm(_realm) >= ((_level) & 0x07 )) ? log_internal_realm(((_realm) << 10 | (_level)), _e , "../src/udev/cdrom_id/cdrom_id.c", 966, __func__, "START_STOP_UNIT (eject)" ) : -abs(_e); }); | |||
| 967 | media_eject(udev, fd); | |||
| 968 | } | |||
| 969 | ||||
| 970 | printf("ID_CDROM=1\n"); | |||
| 971 | if (cd_cd_rom) | |||
| 972 | printf("ID_CDROM_CD=1\n"); | |||
| 973 | if (cd_cd_r) | |||
| 974 | printf("ID_CDROM_CD_R=1\n"); | |||
| 975 | if (cd_cd_rw) | |||
| 976 | printf("ID_CDROM_CD_RW=1\n"); | |||
| 977 | if (cd_dvd_rom) | |||
| 978 | printf("ID_CDROM_DVD=1\n"); | |||
| 979 | if (cd_dvd_r) | |||
| 980 | printf("ID_CDROM_DVD_R=1\n"); | |||
| 981 | if (cd_dvd_rw) | |||
| 982 | printf("ID_CDROM_DVD_RW=1\n"); | |||
| 983 | if (cd_dvd_ram) | |||
| 984 | printf("ID_CDROM_DVD_RAM=1\n"); | |||
| 985 | if (cd_dvd_plus_r) | |||
| 986 | printf("ID_CDROM_DVD_PLUS_R=1\n"); | |||
| 987 | if (cd_dvd_plus_rw) | |||
| 988 | printf("ID_CDROM_DVD_PLUS_RW=1\n"); | |||
| 989 | if (cd_dvd_plus_r_dl) | |||
| 990 | printf("ID_CDROM_DVD_PLUS_R_DL=1\n"); | |||
| 991 | if (cd_dvd_plus_rw_dl) | |||
| 992 | printf("ID_CDROM_DVD_PLUS_RW_DL=1\n"); | |||
| 993 | if (cd_bd) | |||
| 994 | printf("ID_CDROM_BD=1\n"); | |||
| 995 | if (cd_bd_r) | |||
| 996 | printf("ID_CDROM_BD_R=1\n"); | |||
| 997 | if (cd_bd_re) | |||
| 998 | printf("ID_CDROM_BD_RE=1\n"); | |||
| 999 | if (cd_hddvd) | |||
| 1000 | printf("ID_CDROM_HDDVD=1\n"); | |||
| 1001 | if (cd_hddvd_r) | |||
| 1002 | printf("ID_CDROM_HDDVD_R=1\n"); | |||
| 1003 | if (cd_hddvd_rw) | |||
| 1004 | printf("ID_CDROM_HDDVD_RW=1\n"); | |||
| 1005 | if (cd_mo) | |||
| 1006 | printf("ID_CDROM_MO=1\n"); | |||
| 1007 | if (cd_mrw) | |||
| 1008 | printf("ID_CDROM_MRW=1\n"); | |||
| 1009 | if (cd_mrw_w) | |||
| 1010 | printf("ID_CDROM_MRW_W=1\n"); | |||
| 1011 | ||||
| 1012 | if (cd_media) | |||
| 1013 | printf("ID_CDROM_MEDIA=1\n"); | |||
| 1014 | if (cd_media_mo) | |||
| 1015 | printf("ID_CDROM_MEDIA_MO=1\n"); | |||
| 1016 | if (cd_media_mrw) | |||
| 1017 | printf("ID_CDROM_MEDIA_MRW=1\n"); | |||
| 1018 | if (cd_media_mrw_w) | |||
| 1019 | printf("ID_CDROM_MEDIA_MRW_W=1\n"); | |||
| 1020 | if (cd_media_cd_rom) | |||
| 1021 | printf("ID_CDROM_MEDIA_CD=1\n"); | |||
| 1022 | if (cd_media_cd_r) | |||
| 1023 | printf("ID_CDROM_MEDIA_CD_R=1\n"); | |||
| 1024 | if (cd_media_cd_rw) | |||
| 1025 | printf("ID_CDROM_MEDIA_CD_RW=1\n"); | |||
| 1026 | if (cd_media_dvd_rom) | |||
| 1027 | printf("ID_CDROM_MEDIA_DVD=1\n"); | |||
| 1028 | if (cd_media_dvd_r) | |||
| 1029 | printf("ID_CDROM_MEDIA_DVD_R=1\n"); | |||
| 1030 | if (cd_media_dvd_ram) | |||
| 1031 | printf("ID_CDROM_MEDIA_DVD_RAM=1\n"); | |||
| 1032 | if (cd_media_dvd_rw) | |||
| 1033 | printf("ID_CDROM_MEDIA_DVD_RW=1\n"); | |||
| 1034 | if (cd_media_dvd_plus_r) | |||
| 1035 | printf("ID_CDROM_MEDIA_DVD_PLUS_R=1\n"); | |||
| 1036 | if (cd_media_dvd_plus_rw) | |||
| 1037 | printf("ID_CDROM_MEDIA_DVD_PLUS_RW=1\n"); | |||
| 1038 | if (cd_media_dvd_plus_rw_dl) | |||
| 1039 | printf("ID_CDROM_MEDIA_DVD_PLUS_RW_DL=1\n"); | |||
| 1040 | if (cd_media_dvd_plus_r_dl) | |||
| 1041 | printf("ID_CDROM_MEDIA_DVD_PLUS_R_DL=1\n"); | |||
| 1042 | if (cd_media_bd) | |||
| 1043 | printf("ID_CDROM_MEDIA_BD=1\n"); | |||
| 1044 | if (cd_media_bd_r) | |||
| 1045 | printf("ID_CDROM_MEDIA_BD_R=1\n"); | |||
| 1046 | if (cd_media_bd_re) | |||
| 1047 | printf("ID_CDROM_MEDIA_BD_RE=1\n"); | |||
| 1048 | if (cd_media_hddvd) | |||
| 1049 | printf("ID_CDROM_MEDIA_HDDVD=1\n"); | |||
| 1050 | if (cd_media_hddvd_r) | |||
| 1051 | printf("ID_CDROM_MEDIA_HDDVD_R=1\n"); | |||
| 1052 | if (cd_media_hddvd_rw) | |||
| 1053 | printf("ID_CDROM_MEDIA_HDDVD_RW=1\n"); | |||
| 1054 | ||||
| 1055 | if (cd_media_state != NULL((void*)0)) | |||
| 1056 | printf("ID_CDROM_MEDIA_STATE=%s\n", cd_media_state); | |||
| 1057 | if (cd_media_session_next > 0) | |||
| 1058 | printf("ID_CDROM_MEDIA_SESSION_NEXT=%u\n", cd_media_session_next); | |||
| 1059 | if (cd_media_session_count > 0) | |||
| 1060 | printf("ID_CDROM_MEDIA_SESSION_COUNT=%u\n", cd_media_session_count); | |||
| 1061 | if (cd_media_session_count > 1 && cd_media_session_last_offset > 0) | |||
| 1062 | printf("ID_CDROM_MEDIA_SESSION_LAST_OFFSET=%llu\n", cd_media_session_last_offset); | |||
| 1063 | if (cd_media_track_count > 0) | |||
| 1064 | printf("ID_CDROM_MEDIA_TRACK_COUNT=%u\n", cd_media_track_count); | |||
| 1065 | if (cd_media_track_count_audio > 0) | |||
| 1066 | printf("ID_CDROM_MEDIA_TRACK_COUNT_AUDIO=%u\n", cd_media_track_count_audio); | |||
| 1067 | if (cd_media_track_count_data > 0) | |||
| 1068 | printf("ID_CDROM_MEDIA_TRACK_COUNT_DATA=%u\n", cd_media_track_count_data); | |||
| 1069 | exit: | |||
| 1070 | if (fd >= 0) | |||
| 1071 | close(fd); | |||
| 1072 | udev_unref(udev); | |||
| 1073 | log_close(); | |||
| 1074 | return rc; | |||
| 1075 | } |