X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=extras%2Fcdrom_id%2Fcdrom_id.c;h=afb481d1a88fd953af6b4a417ac9631ecb4659be;hp=c578f12921a0113ceb5180f6404634011ac0dee3;hb=c1b7f60deac0bc0e87a139648d57085512fd9e62;hpb=55d8f5e208396589476583dad8f2a7f2db3e2ef5 diff --git a/extras/cdrom_id/cdrom_id.c b/extras/cdrom_id/cdrom_id.c index c578f1292..afb481d1a 100644 --- a/extras/cdrom_id/cdrom_id.c +++ b/extras/cdrom_id/cdrom_id.c @@ -1,7 +1,7 @@ /* * cdrom_id - optical drive and media information prober * - * Copyright (C) 2008 Kay Sievers + * Copyright (C) 2008-2010 Kay Sievers * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,6 +30,7 @@ #include #include #include +#include #include #include #include @@ -37,7 +38,8 @@ #include #include -#include "../../udev/udev.h" +#include "libudev.h" +#include "libudev-private.h" static int debug; @@ -54,62 +56,86 @@ static void log_fn(struct udev *udev, int priority, } /* device info */ -static unsigned int cd_cd_rom; -static unsigned int cd_cd_r; -static unsigned int cd_cd_rw; -static unsigned int cd_dvd_rom; -static unsigned int cd_dvd_r; -static unsigned int cd_dvd_rw; -static unsigned int cd_dvd_ram; -static unsigned int cd_dvd_plus_r; -static unsigned int cd_dvd_plus_rw; -static unsigned int cd_dvd_plus_r_dl; -static unsigned int cd_dvd_plus_rw_dl; -static unsigned int cd_bd; -static unsigned int cd_bd_r; -static unsigned int cd_bd_re; -static unsigned int cd_hddvd; -static unsigned int cd_hddvd_r; -static unsigned int cd_hddvd_rw; -static unsigned int cd_mo; -static unsigned int cd_mrw; -static unsigned int cd_mrw_w; +static unsigned int cd_cd_rom = 0; +static unsigned int cd_cd_r = 0; +static unsigned int cd_cd_rw = 0; +static unsigned int cd_dvd_rom = 0; +static unsigned int cd_dvd_r = 0; +static unsigned int cd_dvd_rw = 0; +static unsigned int cd_dvd_ram = 0; +static unsigned int cd_dvd_plus_r = 0; +static unsigned int cd_dvd_plus_rw = 0; +static unsigned int cd_dvd_plus_r_dl = 0; +static unsigned int cd_dvd_plus_rw_dl = 0; +static unsigned int cd_bd = 0; +static unsigned int cd_bd_r = 0; +static unsigned int cd_bd_re = 0; +static unsigned int cd_hddvd = 0; +static unsigned int cd_hddvd_r = 0; +static unsigned int cd_hddvd_rw = 0; +static unsigned int cd_mo = 0; +static unsigned int cd_mrw = 0; +static unsigned int cd_mrw_w = 0; /* media info */ -static unsigned int cd_media_cd_rom; -static unsigned int cd_media_cd_r; -static unsigned int cd_media_cd_rw; -static unsigned int cd_media_dvd_rom; -static unsigned int cd_media_dvd_r; -static unsigned int cd_media_dvd_rw; -static unsigned int cd_media_dvd_ram; -static unsigned int cd_media_dvd_plus_r; -static unsigned int cd_media_dvd_plus_rw; -static unsigned int cd_media_dvd_plus_r_dl; -static unsigned int cd_media_dvd_plus_rw_dl; -static unsigned int cd_media_bd; -static unsigned int cd_media_bd_r; -static unsigned int cd_media_bd_re; -static unsigned int cd_media_hddvd; -static unsigned int cd_media_hddvd_r; -static unsigned int cd_media_hddvd_rw; -static unsigned int cd_media_mo; -static unsigned int cd_media_mrw; -static unsigned int cd_media_mrw_w; - -static const char *cd_media_state; -static unsigned int cd_media_session_next; -static unsigned int cd_media_session_count; -static unsigned int cd_media_track_count; -static unsigned int cd_media_track_count_data; -static unsigned int cd_media_track_count_audio; -static unsigned long long int cd_media_session_last_offset; +static unsigned int cd_media = 0; +static unsigned int cd_media_cd_rom = 0; +static unsigned int cd_media_cd_r = 0; +static unsigned int cd_media_cd_rw = 0; +static unsigned int cd_media_dvd_rom = 0; +static unsigned int cd_media_dvd_r = 0; +static unsigned int cd_media_dvd_rw = 0; +static unsigned int cd_media_dvd_ram = 0; +static unsigned int cd_media_dvd_plus_r = 0; +static unsigned int cd_media_dvd_plus_rw = 0; +static unsigned int cd_media_dvd_plus_r_dl = 0; +static unsigned int cd_media_dvd_plus_rw_dl = 0; +static unsigned int cd_media_bd = 0; +static unsigned int cd_media_bd_r = 0; +static unsigned int cd_media_bd_re = 0; +static unsigned int cd_media_hddvd = 0; +static unsigned int cd_media_hddvd_r = 0; +static unsigned int cd_media_hddvd_rw = 0; +static unsigned int cd_media_mo = 0; +static unsigned int cd_media_mrw = 0; +static unsigned int cd_media_mrw_w = 0; + +static const char *cd_media_state = NULL; +static unsigned int cd_media_session_next = 0; +static unsigned int cd_media_session_count = 0; +static unsigned int cd_media_track_count = 0; +static unsigned int cd_media_track_count_data = 0; +static unsigned int cd_media_track_count_audio = 0; +static unsigned long long int cd_media_session_last_offset = 0; #define ERRCODE(s) ((((s)[2] & 0x0F) << 16) | ((s)[12] << 8) | ((s)[13])) #define SK(errcode) (((errcode) >> 16) & 0xF) #define ASC(errcode) (((errcode) >> 8) & 0xFF) #define ASCQ(errcode) ((errcode) & 0xFF) +static int is_mounted(const char *device) +{ + struct stat statbuf; + FILE *fp; + int maj, min; + int mounted = 0; + + if (stat(device, &statbuf) < 0) + return -ENODEV; + + fp = fopen("/proc/self/mountinfo", "r"); + if (fp == NULL) + return -ENOSYS; + while (fscanf(fp, "%*s %*s %i:%i %*[^\n]", &maj, &min) == 2) { + if (makedev(maj, min) == statbuf.st_rdev) { + mounted = 1; + break; + } + } + fclose(fp); + return mounted; +} + static void info_scsi_cmd_err(struct udev *udev, char *cmd, int err) { if (err == -1) { @@ -131,7 +157,7 @@ struct scsi_cmd { static void scsi_cmd_set(struct udev *udev, struct scsi_cmd *cmd, size_t i, int arg) { if (i == 0) { - memset(cmd, 0x00, sizeof(struct scsi_cmd)); + memset(cmd, 0, sizeof(struct scsi_cmd)); cmd->cgc.quiet = 1; cmd->cgc.sense = &cmd->_sense.s; memset(&cmd->sg_io, 0, sizeof(cmd->sg_io)); @@ -171,36 +197,47 @@ static int scsi_cmd_run(struct udev *udev, struct scsi_cmd *cmd, int fd, unsigne static int cd_capability_compat(struct udev *udev, int fd) { - int capabilty; + int capability; - capabilty = ioctl(fd, CDROM_GET_CAPABILITY, NULL); - if (capabilty < 0) { + capability = ioctl(fd, CDROM_GET_CAPABILITY, NULL); + if (capability < 0) { info(udev, "CDROM_GET_CAPABILITY failed\n"); return -1; } - if (capabilty & CDC_CD_R) + if (capability & CDC_CD_R) cd_cd_r = 1; - if (capabilty & CDC_CD_RW) + if (capability & CDC_CD_RW) cd_cd_rw = 1; - if (capabilty & CDC_DVD) + if (capability & CDC_DVD) cd_dvd_rom = 1; - if (capabilty & CDC_DVD_R) + if (capability & CDC_DVD_R) cd_dvd_r = 1; - if (capabilty & CDC_DVD_RAM) + if (capability & CDC_DVD_RAM) cd_dvd_ram = 1; - if (capabilty & CDC_MRW) + if (capability & CDC_MRW) cd_mrw = 1; - if (capabilty & CDC_MRW_W) + if (capability & CDC_MRW_W) cd_mrw_w = 1; return 0; } +static int cd_media_compat(struct udev *udev, int fd) +{ + if (ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) != CDS_DISC_OK) { + info(udev, "CDROM_DRIVE_STATUS != CDS_DISC_OK\n"); + return -1; + } + cd_media = 1; + return 0; +} + static int cd_inquiry(struct udev *udev, int fd) { struct scsi_cmd sc; unsigned char inq[128]; int err; + memset(inq, 0, sizeof(inq)); scsi_cmd_set(udev, &sc, 0, 0x12); scsi_cmd_set(udev, &sc, 4, 36); scsi_cmd_set(udev, &sc, 5, 0); @@ -229,6 +266,7 @@ static int cd_profiles(struct udev *udev, int fd) unsigned int i; int err; + memset(header, 0, sizeof(header)); scsi_cmd_set(udev, &sc, 0, 0x46); scsi_cmd_set(udev, &sc, 1, 0); scsi_cmd_set(udev, &sc, 8, sizeof(header)); @@ -246,6 +284,7 @@ static int cd_profiles(struct udev *udev, int fd) return -1; } + memset(profiles, 0, sizeof(profiles)); scsi_cmd_set(udev, &sc, 0, 0x46); scsi_cmd_set(udev, &sc, 1, 1); scsi_cmd_set(udev, &sc, 6, len >> 16); @@ -325,6 +364,8 @@ static int cd_profiles(struct udev *udev, int fd) return -1; } + cd_media = 1; + switch (cur_profile) { case 0x03: case 0x04: @@ -402,6 +443,7 @@ static int cd_media_info(struct udev *udev, int fd) }; int err; + memset(header, 0, sizeof(header)); scsi_cmd_set(udev, &sc, 0, 0x51); scsi_cmd_set(udev, &sc, 8, sizeof(header)); scsi_cmd_set(udev, &sc, 9, 0); @@ -413,8 +455,10 @@ static int cd_media_info(struct udev *udev, int fd) info(udev, "disk type %02x\n", header[8]); - if ((header[2] & 3) < 4) + /* exclude plain CDROM, some fake cdroms return 0 for "blank" media here */ + if (!cd_media_cd_rom && (header[2] & 3) < 4) cd_media_state = media_status[header[2] & 3]; + if ((header[2] & 3) != 2) cd_media_session_next = header[10] << 8 | header[5]; cd_media_session_count = header[9] << 8 | header[4]; @@ -432,6 +476,7 @@ static int cd_media_toc(struct udev *udev, int fd) unsigned char *p; int err; + memset(header, 0, sizeof(header)); scsi_cmd_set(udev, &sc, 0, 0x43); scsi_cmd_set(udev, &sc, 6, 1); scsi_cmd_set(udev, &sc, 8, sizeof(header)); @@ -453,6 +498,7 @@ static int cd_media_toc(struct udev *udev, int fd) if (len < 8) return 0; + memset(toc, 0, sizeof(toc)); scsi_cmd_set(udev, &sc, 0, 0x43); scsi_cmd_set(udev, &sc, 6, header[2]); /* First Track/Session Number */ scsi_cmd_set(udev, &sc, 7, len >> 8); @@ -480,6 +526,7 @@ static int cd_media_toc(struct udev *udev, int fd) cd_media_track_count_audio++; } + memset(header, 0, sizeof (header)); scsi_cmd_set(udev, &sc, 0, 0x43); scsi_cmd_set(udev, &sc, 2, 1); /* Session Info */ scsi_cmd_set(udev, &sc, 8, 12); @@ -507,13 +554,14 @@ int main(int argc, char *argv[]) const char *node = NULL; int export = 0; int fd = -1; + int cnt; int rc = 0; udev = udev_new(); if (udev == NULL) goto exit; - logging_init("cdrom_id"); + udev_log_init("cdrom_id"); udev_set_log_fn(udev, log_fn); while (1) { @@ -552,9 +600,20 @@ int main(int argc, char *argv[]) goto exit; } - fd = open(node, O_RDONLY | O_NONBLOCK); + srand((unsigned int)getpid()); + for (cnt = 20; cnt > 0; cnt--) { + struct timespec duration; + + fd = open(node, O_RDONLY|O_NONBLOCK|(is_mounted(node) ? 0 : O_EXCL)); + if (fd >= 0 || errno != EBUSY) + break; + duration.tv_sec = 0; + duration.tv_nsec = (100 * 1000 * 1000) + (rand() % 100 * 1000 * 1000); + nanosleep(&duration, NULL); + } if (fd < 0) { info(udev, "unable to open '%s'\n", node); + fprintf(stderr, "unable to open '%s'\n", node); rc = 1; goto exit; } @@ -566,7 +625,11 @@ int main(int argc, char *argv[]) goto exit; } - /* check drive */ + /* check for media - don't bail if there's no media as we still need to + * to read profiles */ + cd_media_compat(udev, fd); + + /* check if drive talks MMC */ if (cd_inquiry(udev, fd) < 0) goto print; @@ -625,6 +688,8 @@ print: if (cd_mrw_w) printf("ID_CDROM_MRW_W=1\n"); + if (cd_media) + printf("ID_CDROM_MEDIA=1\n"); if (cd_media_mo) printf("ID_CDROM_MEDIA_MO=1\n"); if (cd_media_mrw) @@ -684,7 +749,7 @@ exit: if (fd >= 0) close(fd); udev_unref(udev); - logging_close(); + udev_log_close(); return rc; }