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