udev/cdrom: introduce Context
This commit is contained in:
parent
0f0b079135
commit
e5aac5cdf1
|
@ -21,6 +21,7 @@
|
||||||
#include <time.h>
|
#include <time.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include "fd-util.h"
|
||||||
#include "log.h"
|
#include "log.h"
|
||||||
#include "memory-util.h"
|
#include "memory-util.h"
|
||||||
#include "random-util.h"
|
#include "random-util.h"
|
||||||
|
@ -31,6 +32,10 @@ static bool arg_lock = false;
|
||||||
static bool arg_unlock = false;
|
static bool arg_unlock = false;
|
||||||
static const char *arg_node = NULL;
|
static const char *arg_node = NULL;
|
||||||
|
|
||||||
|
typedef struct Context {
|
||||||
|
int fd;
|
||||||
|
} Context;
|
||||||
|
|
||||||
/* device info */
|
/* device info */
|
||||||
static unsigned cd_rw_nonremovable;
|
static unsigned cd_rw_nonremovable;
|
||||||
static unsigned cd_rw_removable;
|
static unsigned cd_rw_removable;
|
||||||
|
@ -124,6 +129,21 @@ static unsigned cd_media_track_count_data;
|
||||||
static unsigned cd_media_track_count_audio;
|
static unsigned cd_media_track_count_audio;
|
||||||
static unsigned long long int cd_media_session_last_offset;
|
static unsigned long long int cd_media_session_last_offset;
|
||||||
|
|
||||||
|
static void context_clear(Context *c) {
|
||||||
|
if (!c)
|
||||||
|
return;
|
||||||
|
|
||||||
|
safe_close(c->fd);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void context_init(Context *c) {
|
||||||
|
assert(c);
|
||||||
|
|
||||||
|
*c = (Context) {
|
||||||
|
.fd = -1,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
#define ERRCODE(s) ((((s)[2] & 0x0F) << 16) | ((s)[12] << 8) | ((s)[13]))
|
#define ERRCODE(s) ((((s)[2] & 0x0F) << 16) | ((s)[12] << 8) | ((s)[13]))
|
||||||
#define SK(errcode) (((errcode) >> 16) & 0xF)
|
#define SK(errcode) (((errcode) >> 16) & 0xF)
|
||||||
#define ASC(errcode) (((errcode) >> 8) & 0xFF)
|
#define ASC(errcode) (((errcode) >> 8) & 0xFF)
|
||||||
|
@ -233,10 +253,12 @@ static int media_eject(int fd) {
|
||||||
return scsi_cmd_run_and_log(&sc, fd, NULL, 0, "start/stop unit");
|
return scsi_cmd_run_and_log(&sc, fd, NULL, 0, "start/stop unit");
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cd_capability_compat(int fd) {
|
static int cd_capability_compat(Context *c) {
|
||||||
int capability;
|
int capability;
|
||||||
|
|
||||||
capability = ioctl(fd, CDROM_GET_CAPABILITY, NULL);
|
assert(c);
|
||||||
|
|
||||||
|
capability = ioctl(c->fd, CDROM_GET_CAPABILITY, NULL);
|
||||||
if (capability < 0)
|
if (capability < 0)
|
||||||
return log_debug_errno(errno, "CDROM_GET_CAPABILITY failed");
|
return log_debug_errno(errno, "CDROM_GET_CAPABILITY failed");
|
||||||
|
|
||||||
|
@ -257,24 +279,28 @@ static int cd_capability_compat(int fd) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cd_media_compat(int fd) {
|
static int cd_media_compat(Context *c) {
|
||||||
if (ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) != CDS_DISC_OK)
|
assert(c);
|
||||||
|
|
||||||
|
if (ioctl(c->fd, CDROM_DRIVE_STATUS, CDSL_CURRENT) != CDS_DISC_OK)
|
||||||
return log_debug_errno(errno, "CDROM_DRIVE_STATUS != CDS_DISC_OK");
|
return log_debug_errno(errno, "CDROM_DRIVE_STATUS != CDS_DISC_OK");
|
||||||
|
|
||||||
cd_media = 1;
|
cd_media = 1;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cd_inquiry(int fd) {
|
static int cd_inquiry(Context *c) {
|
||||||
struct scsi_cmd sc;
|
struct scsi_cmd sc;
|
||||||
unsigned char inq[36];
|
unsigned char inq[36];
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
assert(c);
|
||||||
|
|
||||||
scsi_cmd_init(&sc);
|
scsi_cmd_init(&sc);
|
||||||
scsi_cmd_set(&sc, 0, GPCMD_INQUIRY);
|
scsi_cmd_set(&sc, 0, GPCMD_INQUIRY);
|
||||||
scsi_cmd_set(&sc, 4, sizeof(inq));
|
scsi_cmd_set(&sc, 4, sizeof(inq));
|
||||||
scsi_cmd_set(&sc, 5, 0);
|
scsi_cmd_set(&sc, 5, 0);
|
||||||
r = scsi_cmd_run_and_log(&sc, fd, inq, sizeof(inq), "inquire");
|
r = scsi_cmd_run_and_log(&sc, c->fd, inq, sizeof(inq), "inquire");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -635,18 +661,19 @@ static int feature_profiles(const unsigned char *profiles, size_t size) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cd_profiles_old_mmc(int fd) {
|
static int cd_profiles_old_mmc(Context *c) {
|
||||||
|
disc_information discinfo;
|
||||||
struct scsi_cmd sc;
|
struct scsi_cmd sc;
|
||||||
size_t len;
|
size_t len;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
disc_information discinfo;
|
assert(c);
|
||||||
|
|
||||||
scsi_cmd_init(&sc);
|
scsi_cmd_init(&sc);
|
||||||
scsi_cmd_set(&sc, 0, GPCMD_READ_DISC_INFO);
|
scsi_cmd_set(&sc, 0, GPCMD_READ_DISC_INFO);
|
||||||
scsi_cmd_set(&sc, 8, sizeof(discinfo.disc_information_length));
|
scsi_cmd_set(&sc, 8, sizeof(discinfo.disc_information_length));
|
||||||
scsi_cmd_set(&sc, 9, 0);
|
scsi_cmd_set(&sc, 9, 0);
|
||||||
r = scsi_cmd_run_and_log(&sc, fd, (unsigned char *)&discinfo.disc_information_length, sizeof(discinfo.disc_information_length), "read disc information");
|
r = scsi_cmd_run_and_log(&sc, c->fd, (unsigned char *)&discinfo.disc_information_length, sizeof(discinfo.disc_information_length), "read disc information");
|
||||||
if (r >= 0) {
|
if (r >= 0) {
|
||||||
/* Not all drives have the same disc_info length, so requeue
|
/* Not all drives have the same disc_info length, so requeue
|
||||||
* packet with the length the drive tells us it can supply */
|
* packet with the length the drive tells us it can supply */
|
||||||
|
@ -658,7 +685,7 @@ static int cd_profiles_old_mmc(int fd) {
|
||||||
scsi_cmd_set(&sc, 0, GPCMD_READ_DISC_INFO);
|
scsi_cmd_set(&sc, 0, GPCMD_READ_DISC_INFO);
|
||||||
scsi_cmd_set(&sc, 8, len);
|
scsi_cmd_set(&sc, 8, len);
|
||||||
scsi_cmd_set(&sc, 9, 0);
|
scsi_cmd_set(&sc, 9, 0);
|
||||||
r = scsi_cmd_run_and_log(&sc, fd, (unsigned char *)&discinfo, len, "read disc information");
|
r = scsi_cmd_run_and_log(&sc, c->fd, (unsigned char *)&discinfo, len, "read disc information");
|
||||||
}
|
}
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
if (cd_media == 1) {
|
if (cd_media == 1) {
|
||||||
|
@ -688,7 +715,7 @@ static int cd_profiles_old_mmc(int fd) {
|
||||||
return 1;
|
return 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cd_profiles(int fd) {
|
static int cd_profiles(Context *c) {
|
||||||
struct scsi_cmd sc;
|
struct scsi_cmd sc;
|
||||||
unsigned char features[65530];
|
unsigned char features[65530];
|
||||||
unsigned cur_profile = 0;
|
unsigned cur_profile = 0;
|
||||||
|
@ -697,18 +724,20 @@ static int cd_profiles(int fd) {
|
||||||
bool has_media = false;
|
bool has_media = false;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
assert(c);
|
||||||
|
|
||||||
/* First query the current profile */
|
/* First query the current profile */
|
||||||
scsi_cmd_init(&sc);
|
scsi_cmd_init(&sc);
|
||||||
scsi_cmd_set(&sc, 0, GPCMD_GET_CONFIGURATION);
|
scsi_cmd_set(&sc, 0, GPCMD_GET_CONFIGURATION);
|
||||||
scsi_cmd_set(&sc, 8, 8);
|
scsi_cmd_set(&sc, 8, 8);
|
||||||
scsi_cmd_set(&sc, 9, 0);
|
scsi_cmd_set(&sc, 9, 0);
|
||||||
r = scsi_cmd_run(&sc, fd, features, 8);
|
r = scsi_cmd_run(&sc, c->fd, features, 8);
|
||||||
if (r != 0) {
|
if (r != 0) {
|
||||||
/* handle pre-MMC2 drives which do not support GET CONFIGURATION */
|
/* handle pre-MMC2 drives which do not support GET CONFIGURATION */
|
||||||
if (r > 0 && SK(r) == 0x5 && IN_SET(ASC(r), 0x20, 0x24)) {
|
if (r > 0 && SK(r) == 0x5 && IN_SET(ASC(r), 0x20, 0x24)) {
|
||||||
log_debug("Drive is pre-MMC2 and does not support 46h get configuration command; "
|
log_debug("Drive is pre-MMC2 and does not support 46h get configuration command; "
|
||||||
"trying to work around the problem.");
|
"trying to work around the problem.");
|
||||||
return cd_profiles_old_mmc(fd);
|
return cd_profiles_old_mmc(c);
|
||||||
}
|
}
|
||||||
|
|
||||||
return log_scsi_debug_errno(r, "get configuration");
|
return log_scsi_debug_errno(r, "get configuration");
|
||||||
|
@ -737,7 +766,7 @@ static int cd_profiles(int fd) {
|
||||||
scsi_cmd_set(&sc, 7, ( len >> 8 ) & 0xff);
|
scsi_cmd_set(&sc, 7, ( len >> 8 ) & 0xff);
|
||||||
scsi_cmd_set(&sc, 8, len & 0xff);
|
scsi_cmd_set(&sc, 8, len & 0xff);
|
||||||
scsi_cmd_set(&sc, 9, 0);
|
scsi_cmd_set(&sc, 9, 0);
|
||||||
r = scsi_cmd_run_and_log(&sc, fd, features, len, "get configuration");
|
r = scsi_cmd_run_and_log(&sc, c->fd, features, len, "get configuration");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -770,7 +799,7 @@ static int cd_profiles(int fd) {
|
||||||
return has_media;
|
return has_media;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cd_media_info(int fd) {
|
static int cd_media_info(Context *c) {
|
||||||
struct scsi_cmd sc;
|
struct scsi_cmd sc;
|
||||||
unsigned char header[32];
|
unsigned char header[32];
|
||||||
static const char *const media_status[] = {
|
static const char *const media_status[] = {
|
||||||
|
@ -781,11 +810,13 @@ static int cd_media_info(int fd) {
|
||||||
};
|
};
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
assert(c);
|
||||||
|
|
||||||
scsi_cmd_init(&sc);
|
scsi_cmd_init(&sc);
|
||||||
scsi_cmd_set(&sc, 0, GPCMD_READ_DISC_INFO);
|
scsi_cmd_set(&sc, 0, GPCMD_READ_DISC_INFO);
|
||||||
scsi_cmd_set(&sc, 8, sizeof(header));
|
scsi_cmd_set(&sc, 8, sizeof(header));
|
||||||
scsi_cmd_set(&sc, 9, 0);
|
scsi_cmd_set(&sc, 9, 0);
|
||||||
r = scsi_cmd_run_and_log(&sc, fd, header, sizeof(header), "read disc information");
|
r = scsi_cmd_run_and_log(&sc, c->fd, header, sizeof(header), "read disc information");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -822,7 +853,7 @@ static int cd_media_info(int fd) {
|
||||||
scsi_cmd_set(&sc, 7, 0xC0);
|
scsi_cmd_set(&sc, 7, 0xC0);
|
||||||
scsi_cmd_set(&sc, 9, sizeof(dvdstruct));
|
scsi_cmd_set(&sc, 9, sizeof(dvdstruct));
|
||||||
scsi_cmd_set(&sc, 11, 0);
|
scsi_cmd_set(&sc, 11, 0);
|
||||||
r = scsi_cmd_run_and_log(&sc, fd, dvdstruct, sizeof(dvdstruct), "read DVD structure");
|
r = scsi_cmd_run_and_log(&sc, c->fd, dvdstruct, sizeof(dvdstruct), "read DVD structure");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -837,7 +868,7 @@ static int cd_media_info(int fd) {
|
||||||
scsi_cmd_set(&sc, 0, GPCMD_READ_FORMAT_CAPACITIES);
|
scsi_cmd_set(&sc, 0, GPCMD_READ_FORMAT_CAPACITIES);
|
||||||
scsi_cmd_set(&sc, 8, sizeof(format));
|
scsi_cmd_set(&sc, 8, sizeof(format));
|
||||||
scsi_cmd_set(&sc, 9, 0);
|
scsi_cmd_set(&sc, 9, 0);
|
||||||
r = scsi_cmd_run_and_log(&sc, fd, format, sizeof(format), "read DVD format capacities");
|
r = scsi_cmd_run_and_log(&sc, c->fd, format, sizeof(format), "read DVD format capacities");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -876,7 +907,7 @@ static int cd_media_info(int fd) {
|
||||||
scsi_cmd_set(&sc, 5, 0);
|
scsi_cmd_set(&sc, 5, 0);
|
||||||
scsi_cmd_set(&sc, 8, sizeof(buffer)/2048);
|
scsi_cmd_set(&sc, 8, sizeof(buffer)/2048);
|
||||||
scsi_cmd_set(&sc, 9, 0);
|
scsi_cmd_set(&sc, 9, 0);
|
||||||
r = scsi_cmd_run_and_log(&sc, fd, buffer, sizeof(buffer), "read first 32 blocks");
|
r = scsi_cmd_run_and_log(&sc, c->fd, buffer, sizeof(buffer), "read first 32 blocks");
|
||||||
if (r < 0) {
|
if (r < 0) {
|
||||||
cd_media = 0;
|
cd_media = 0;
|
||||||
return r;
|
return r;
|
||||||
|
@ -915,7 +946,7 @@ determined:
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int cd_media_toc(int fd) {
|
static int cd_media_toc(Context *c) {
|
||||||
struct scsi_cmd sc;
|
struct scsi_cmd sc;
|
||||||
unsigned char header[12];
|
unsigned char header[12];
|
||||||
unsigned char toc[65536];
|
unsigned char toc[65536];
|
||||||
|
@ -923,12 +954,14 @@ static int cd_media_toc(int fd) {
|
||||||
unsigned char *p;
|
unsigned char *p;
|
||||||
int r;
|
int r;
|
||||||
|
|
||||||
|
assert(c);
|
||||||
|
|
||||||
scsi_cmd_init(&sc);
|
scsi_cmd_init(&sc);
|
||||||
scsi_cmd_set(&sc, 0, GPCMD_READ_TOC_PMA_ATIP);
|
scsi_cmd_set(&sc, 0, GPCMD_READ_TOC_PMA_ATIP);
|
||||||
scsi_cmd_set(&sc, 6, 1);
|
scsi_cmd_set(&sc, 6, 1);
|
||||||
scsi_cmd_set(&sc, 8, sizeof(header));
|
scsi_cmd_set(&sc, 8, sizeof(header));
|
||||||
scsi_cmd_set(&sc, 9, 0);
|
scsi_cmd_set(&sc, 9, 0);
|
||||||
r = scsi_cmd_run_and_log(&sc, fd, header, sizeof(header), "read TOC");
|
r = scsi_cmd_run_and_log(&sc, c->fd, header, sizeof(header), "read TOC");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -951,7 +984,7 @@ static int cd_media_toc(int fd) {
|
||||||
scsi_cmd_set(&sc, 7, (len >> 8) & 0xff);
|
scsi_cmd_set(&sc, 7, (len >> 8) & 0xff);
|
||||||
scsi_cmd_set(&sc, 8, len & 0xff);
|
scsi_cmd_set(&sc, 8, len & 0xff);
|
||||||
scsi_cmd_set(&sc, 9, 0);
|
scsi_cmd_set(&sc, 9, 0);
|
||||||
r = scsi_cmd_run_and_log(&sc, fd, toc, len, "read TOC (tracks)");
|
r = scsi_cmd_run_and_log(&sc, c->fd, toc, len, "read TOC (tracks)");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -979,7 +1012,7 @@ static int cd_media_toc(int fd) {
|
||||||
scsi_cmd_set(&sc, 2, 1); /* Session Info */
|
scsi_cmd_set(&sc, 2, 1); /* Session Info */
|
||||||
scsi_cmd_set(&sc, 8, sizeof(header));
|
scsi_cmd_set(&sc, 8, sizeof(header));
|
||||||
scsi_cmd_set(&sc, 9, 0);
|
scsi_cmd_set(&sc, 9, 0);
|
||||||
r = scsi_cmd_run_and_log(&sc, fd, header, sizeof(header), "read TOC (multi session)");
|
r = scsi_cmd_run_and_log(&sc, c->fd, header, sizeof(header), "read TOC (multi session)");
|
||||||
if (r < 0)
|
if (r < 0)
|
||||||
return r;
|
return r;
|
||||||
|
|
||||||
|
@ -990,6 +1023,29 @@ static int cd_media_toc(int fd) {
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static int open_drive(Context *c) {
|
||||||
|
_cleanup_close_ int fd = -1;
|
||||||
|
|
||||||
|
assert(c);
|
||||||
|
assert(c->fd < 0);
|
||||||
|
|
||||||
|
for (int cnt = 0; cnt < 20; cnt++) {
|
||||||
|
if (cnt != 0)
|
||||||
|
(void) usleep(100 * USEC_PER_MSEC + random_u64() % (100 * USEC_PER_MSEC));
|
||||||
|
|
||||||
|
fd = open(arg_node, O_RDONLY|O_NONBLOCK|O_CLOEXEC);
|
||||||
|
if (fd >= 0 || errno != EBUSY)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
if (fd < 0)
|
||||||
|
return log_debug_errno(errno, "Unable to open '%s'", arg_node);
|
||||||
|
|
||||||
|
log_debug("probing: '%s'", arg_node);
|
||||||
|
|
||||||
|
c->fd = TAKE_FD(fd);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
static int help(void) {
|
static int help(void) {
|
||||||
printf("Usage: %s [options] <device>\n"
|
printf("Usage: %s [options] <device>\n"
|
||||||
" -l --lock-media lock the media (to enable eject request events)\n"
|
" -l --lock-media lock the media (to enable eject request events)\n"
|
||||||
|
@ -1044,79 +1100,70 @@ static int parse_argv(int argc, char *argv[]) {
|
||||||
}
|
}
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
int main(int argc, char *argv[]) {
|
||||||
int fd = -1;
|
_cleanup_(context_clear) Context c;
|
||||||
int rc = 0;
|
int r, rc = 0;
|
||||||
int r;
|
|
||||||
|
|
||||||
log_set_target(LOG_TARGET_AUTO);
|
log_set_target(LOG_TARGET_AUTO);
|
||||||
udev_parse_config();
|
udev_parse_config();
|
||||||
log_parse_environment();
|
log_parse_environment();
|
||||||
log_open();
|
log_open();
|
||||||
|
|
||||||
|
context_init(&c);
|
||||||
|
|
||||||
r = parse_argv(argc, argv);
|
r = parse_argv(argc, argv);
|
||||||
if (r <= 0) {
|
if (r <= 0) {
|
||||||
rc = r < 0;
|
rc = r < 0;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
for (int cnt = 0; cnt < 20; cnt++) {
|
if (open_drive(&c) < 0) {
|
||||||
if (cnt != 0)
|
|
||||||
(void) usleep(100 * USEC_PER_MSEC + random_u64() % (100 * USEC_PER_MSEC));
|
|
||||||
|
|
||||||
fd = open(arg_node, O_RDONLY|O_NONBLOCK|O_CLOEXEC);
|
|
||||||
if (fd >= 0 || errno != EBUSY)
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
if (fd < 0) {
|
|
||||||
log_debug("unable to open '%s'", arg_node);
|
|
||||||
rc = 1;
|
rc = 1;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
log_debug("probing: '%s'", arg_node);
|
|
||||||
|
|
||||||
/* same data as original cdrom_id */
|
/* same data as original cdrom_id */
|
||||||
if (cd_capability_compat(fd) < 0) {
|
if (cd_capability_compat(&c) < 0) {
|
||||||
rc = 1;
|
rc = 1;
|
||||||
goto exit;
|
goto exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* check for media - don't bail if there's no media as we still need to
|
/* check for media - don't bail if there's no media as we still need to
|
||||||
* to read profiles */
|
* to read profiles */
|
||||||
cd_media_compat(fd);
|
cd_media_compat(&c);
|
||||||
|
|
||||||
/* check if drive talks MMC */
|
/* check if drive talks MMC */
|
||||||
if (cd_inquiry(fd) < 0)
|
if (cd_inquiry(&c) < 0)
|
||||||
goto work;
|
goto work;
|
||||||
|
|
||||||
/* read drive and possibly current profile */
|
/* read drive and possibly current profile */
|
||||||
r = cd_profiles(fd);
|
r = cd_profiles(&c);
|
||||||
if (r > 0) {
|
if (r > 0) {
|
||||||
/* at this point we are guaranteed to have media in the drive - find out more about it */
|
/* at this point we are guaranteed to have media in the drive - find out more about it */
|
||||||
|
|
||||||
/* get session/track info */
|
/* get session/track info */
|
||||||
cd_media_toc(fd);
|
cd_media_toc(&c);
|
||||||
|
|
||||||
/* get writable media state */
|
/* get writable media state */
|
||||||
cd_media_info(fd);
|
cd_media_info(&c);
|
||||||
}
|
}
|
||||||
|
|
||||||
work:
|
work:
|
||||||
/* lock the media, so we enable eject button events */
|
/* lock the media, so we enable eject button events */
|
||||||
if (arg_lock && cd_media) {
|
if (arg_lock && cd_media) {
|
||||||
log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (lock)");
|
log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (lock)");
|
||||||
media_lock(fd, true);
|
media_lock(c.fd, true);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg_unlock && cd_media) {
|
if (arg_unlock && cd_media) {
|
||||||
log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (unlock)");
|
log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (unlock)");
|
||||||
media_lock(fd, false);
|
media_lock(c.fd, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (arg_eject) {
|
if (arg_eject) {
|
||||||
log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (unlock)");
|
log_debug("PREVENT_ALLOW_MEDIUM_REMOVAL (unlock)");
|
||||||
media_lock(fd, false);
|
media_lock(c.fd, false);
|
||||||
log_debug("START_STOP_UNIT (eject)");
|
log_debug("START_STOP_UNIT (eject)");
|
||||||
media_eject(fd);
|
media_eject(c.fd);
|
||||||
}
|
}
|
||||||
|
|
||||||
printf("ID_CDROM=1\n");
|
printf("ID_CDROM=1\n");
|
||||||
|
@ -1295,8 +1342,6 @@ work:
|
||||||
if (cd_media_track_count_data > 0)
|
if (cd_media_track_count_data > 0)
|
||||||
printf("ID_CDROM_MEDIA_TRACK_COUNT_DATA=%u\n", cd_media_track_count_data);
|
printf("ID_CDROM_MEDIA_TRACK_COUNT_DATA=%u\n", cd_media_track_count_data);
|
||||||
exit:
|
exit:
|
||||||
if (fd >= 0)
|
|
||||||
close(fd);
|
|
||||||
log_close();
|
log_close();
|
||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue