X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=extras%2Fcdrom_id%2Fcdrom_id.c;h=894a8905749e90c203fcbe41d6a06e09a7a868dc;hb=d45c8c8b01c99180f15e24b22f7cf81eaf3cdd1b;hp=7be0789f35bc2bf92013a2571fefb22c07eb7430;hpb=e02d738ee4da950e9228802ea52d9a6f0992c442;p=elogind.git diff --git a/extras/cdrom_id/cdrom_id.c b/extras/cdrom_id/cdrom_id.c index 7be0789f3..894a89057 100644 --- a/extras/cdrom_id/cdrom_id.c +++ b/extras/cdrom_id/cdrom_id.c @@ -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; @@ -76,6 +78,7 @@ static unsigned int cd_mrw; static unsigned int cd_mrw_w; /* media info */ +static unsigned int cd_media; static unsigned int cd_media_cd_rom; static unsigned int cd_media_cd_r; static unsigned int cd_media_cd_rw; @@ -110,6 +113,29 @@ static unsigned long long int cd_media_session_last_offset; #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) { @@ -171,31 +197,41 @@ 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]; @@ -325,6 +361,8 @@ static int cd_profiles(struct udev *udev, int fd) return -1; } + cd_media = 1; + switch (cur_profile) { case 0x03: case 0x04: @@ -413,8 +451,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]; @@ -507,13 +547,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 +593,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,11 +618,13 @@ int main(int argc, char *argv[]) goto exit; } - /* check drive */ - if (cd_inquiry(udev, fd) < 0) { - rc = 2; - goto exit; - } + /* 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; /* read drive and possibly current profile */ if (cd_profiles(udev, fd) < 0) @@ -627,6 +681,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) @@ -686,7 +742,7 @@ exit: if (fd >= 0) close(fd); udev_unref(udev); - logging_close(); + udev_log_close(); return rc; }