Bug in eject: need to close internal file descriptor before ejecting.

eject interface now nulls cdio pointer after a sucessful eject.
This commit is contained in:
rocky
2003-05-16 07:18:27 +00:00
parent 9a7cf3a4ee
commit 8b22196efe
7 changed files with 109 additions and 24 deletions

View File

@@ -1,5 +1,5 @@
/* -*- c -*- /* -*- c -*-
$Id: cdio.h,v 1.6 2003/04/22 12:09:08 rocky Exp $ $Id: cdio.h,v 1.7 2003/05/16 07:18:27 rocky Exp $
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
Copyright (C) 2003 Rocky Bernstein <rocky@panix.com> Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
@@ -103,8 +103,9 @@ extern "C" {
/*! /*!
Eject media in CD drive if there is a routine to do so. Eject media in CD drive if there is a routine to do so.
Return 0 if success and 1 for failure, and 2 if no routine. Return 0 if success and 1 for failure, and 2 if no routine.
If the CD is ejected *obj is freed and obj set to NULL.
*/ */
int cdio_eject_media (const CdIo *obj); int cdio_eject_media (CdIo **obj);
/*! /*!
Free any resources associated with obj. Free any resources associated with obj.

View File

@@ -1,5 +1,5 @@
/* /*
$Id: _cdio_bsdi.c,v 1.9 2003/04/22 12:09:08 rocky Exp $ $Id: _cdio_bsdi.c,v 1.10 2003/05/16 07:18:27 rocky Exp $
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
Copyright (C) 2002,2003 Rocky Bernstein <rocky@panix.com> Copyright (C) 2002,2003 Rocky Bernstein <rocky@panix.com>
@@ -27,7 +27,7 @@
# include "config.h" # include "config.h"
#endif #endif
static const char _rcsid[] = "$Id: _cdio_bsdi.c,v 1.9 2003/04/22 12:09:08 rocky Exp $"; static const char _rcsid[] = "$Id: _cdio_bsdi.c,v 1.10 2003/05/16 07:18:27 rocky Exp $";
#include <cdio/sector.h> #include <cdio/sector.h>
#include <cdio/util.h> #include <cdio/util.h>
@@ -314,6 +314,8 @@ _cdio_eject_media (void *user_data) {
int status; int status;
int fd; int fd;
close(_obj->gen.fd);
_obj->gen.fd = -1;
if ((fd = open (_obj->source_name, O_RDONLY|O_NONBLOCK)) > -1) { if ((fd = open (_obj->source_name, O_RDONLY|O_NONBLOCK)) > -1) {
if((status = ioctl(fd, CDROM_DRIVE_STATUS, (void *) CDSL_CURRENT)) > 0) { if((status = ioctl(fd, CDROM_DRIVE_STATUS, (void *) CDSL_CURRENT)) > 0) {
switch(status) { switch(status) {
@@ -334,7 +336,6 @@ _cdio_eject_media (void *user_data) {
ret=1; ret=1;
} }
close(fd); close(fd);
cdio_generic_free((void *) _obj);
} }
return 2; return 2;
} }

View File

@@ -1,5 +1,5 @@
/* /*
$Id: _cdio_freebsd.c,v 1.9 2003/04/22 12:09:08 rocky Exp $ $Id: _cdio_freebsd.c,v 1.10 2003/05/16 07:18:27 rocky Exp $
Copyright (C) 2003 Rocky Bernstein <rocky@panix.com> Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
@@ -26,7 +26,7 @@
# include "config.h" # include "config.h"
#endif #endif
static const char _rcsid[] = "$Id: _cdio_freebsd.c,v 1.9 2003/04/22 12:09:08 rocky Exp $"; static const char _rcsid[] = "$Id: _cdio_freebsd.c,v 1.10 2003/05/16 07:18:27 rocky Exp $";
#include <cdio/sector.h> #include <cdio/sector.h>
#include <cdio/util.h> #include <cdio/util.h>
@@ -361,7 +361,6 @@ _cdio_eject_media (void *user_data) {
ret = 0; ret = 0;
} }
close(fd); close(fd);
_cdio_generic_free((void *) _obj);
} }
return ret; return ret;

View File

@@ -1,5 +1,5 @@
/* /*
$Id: _cdio_linux.c,v 1.11 2003/04/22 12:09:09 rocky Exp $ $Id: _cdio_linux.c,v 1.12 2003/05/16 07:18:27 rocky Exp $
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
Copyright (C) 2002,2003 Rocky Bernstein <rocky@panix.com> Copyright (C) 2002,2003 Rocky Bernstein <rocky@panix.com>
@@ -27,7 +27,7 @@
# include "config.h" # include "config.h"
#endif #endif
static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.11 2003/04/22 12:09:09 rocky Exp $"; static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.12 2003/05/16 07:18:27 rocky Exp $";
#include <string.h> #include <string.h>
@@ -58,6 +58,11 @@ static const char _rcsid[] = "$Id: _cdio_linux.c,v 1.11 2003/04/22 12:09:09 rock
#include <fcntl.h> #include <fcntl.h>
#include <linux/cdrom.h> #include <linux/cdrom.h>
#include <scsi/scsi.h>
#include <scsi/sg.h>
#include <scsi/scsi_ioctl.h>
#include <sys/mount.h>
#include <sys/stat.h> #include <sys/stat.h>
#include <sys/types.h> #include <sys/types.h>
#include <sys/ioctl.h> #include <sys/ioctl.h>
@@ -515,9 +520,63 @@ _cdio_read_toc (_img_private_t *_obj)
return true; return true;
} }
/*
* Eject using SCSI commands. Return 1 if successful, 0 otherwise.
*/
static int
_cdio_eject_scsi(int fd)
{
int status;
struct sdata {
int inlen;
int outlen;
char cmd[256];
} scsi_cmd;
scsi_cmd.inlen = 0;
scsi_cmd.outlen = 0;
scsi_cmd.cmd[0] = ALLOW_MEDIUM_REMOVAL;
scsi_cmd.cmd[1] = 0;
scsi_cmd.cmd[2] = 0;
scsi_cmd.cmd[3] = 0;
scsi_cmd.cmd[4] = 0;
scsi_cmd.cmd[5] = 0;
status = ioctl(fd, SCSI_IOCTL_SEND_COMMAND, (void *)&scsi_cmd);
if (status != 0)
return 0;
scsi_cmd.inlen = 0;
scsi_cmd.outlen = 0;
scsi_cmd.cmd[0] = START_STOP;
scsi_cmd.cmd[1] = 0;
scsi_cmd.cmd[2] = 0;
scsi_cmd.cmd[3] = 0;
scsi_cmd.cmd[4] = 1;
scsi_cmd.cmd[5] = 0;
status = ioctl(fd, SCSI_IOCTL_SEND_COMMAND, (void *)&scsi_cmd);
if (status != 0)
return 0;
scsi_cmd.inlen = 0;
scsi_cmd.outlen = 0;
scsi_cmd.cmd[0] = START_STOP;
scsi_cmd.cmd[1] = 0;
scsi_cmd.cmd[2] = 0;
scsi_cmd.cmd[3] = 0;
scsi_cmd.cmd[4] = 2;
scsi_cmd.cmd[5] = 0;
status = ioctl(fd, SCSI_IOCTL_SEND_COMMAND, (void *)&scsi_cmd);
if (status != 0)
return 0;
/* force kernel to reread partition table when new disc inserted */
status = ioctl(fd, BLKRRPART);
return (status == 0);
}
/*! /*!
Eject media in CD drive. If successful, as a side effect we Eject media in CD drive.
also free obj. Return 0 if success and 1 for failure, and 2 if no routine.
*/ */
static int static int
_cdio_eject_media (void *user_data) { _cdio_eject_media (void *user_data) {
@@ -527,27 +586,38 @@ _cdio_eject_media (void *user_data) {
int status; int status;
int fd; int fd;
close(_obj->gen.fd);
_obj->gen.fd = -1;
if ((fd = open (_obj->gen.source_name, O_RDONLY|O_NONBLOCK)) > -1) { if ((fd = open (_obj->gen.source_name, O_RDONLY|O_NONBLOCK)) > -1) {
if((status = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT)) > 0) { if((status = ioctl(fd, CDROM_DRIVE_STATUS, CDSL_CURRENT)) > 0) {
switch(status) { switch(status) {
case CDS_TRAY_OPEN: case CDS_TRAY_OPEN:
if((ret = ioctl(fd, CDROMCLOSETRAY)) != 0) { if((ret = ioctl(fd, CDROMCLOSETRAY)) != 0) {
cdio_error ("ioctl CDROMCLOSETRAY failed: %s\n", strerror(errno)); cdio_error ("ioctl CDROMCLOSETRAY failed: %s\n", strerror(errno));
ret = 1;
} }
break; break;
case CDS_DISC_OK: case CDS_DISC_OK:
if((ret = ioctl(fd, CDROMEJECT)) != 0) { if((ret = ioctl(fd, CDROMEJECT)) != 0) {
cdio_error("ioctl CDROMEJECT failed: %s\n", strerror(errno)); int eject_error = errno;
/* Try ejecting the SCSI way... */
ret = _cdio_eject_scsi(fd);
if (0 != ret) {
cdio_error("ioctl CDROMEJECT failed: %s\n", strerror(eject_error));
ret = 1;
}
} }
break; break;
default:
cdio_error ("Unknown CD-ROM (%d)\n", status);
ret = 1;
} }
ret=0;
} else { } else {
cdio_error ("CDROM_DRIVE_STATUS failed: %s\n", strerror(errno)); cdio_error ("CDROM_DRIVE_STATUS failed: %s\n", strerror(errno));
ret=1; ret=1;
} }
close(fd); close(fd);
cdio_generic_free((void *) _obj); return ret;
} }
return 2; return 2;
} }

View File

@@ -1,5 +1,5 @@
/* /*
$Id: _cdio_sunos.c,v 1.12 2003/04/22 12:09:09 rocky Exp $ $Id: _cdio_sunos.c,v 1.13 2003/05/16 07:18:27 rocky Exp $
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
Copyright (C) 2002,2003 Rocky Bernstein <rocky@panix.com> Copyright (C) 2002,2003 Rocky Bernstein <rocky@panix.com>
@@ -35,7 +35,7 @@
#ifdef HAVE_SOLARIS_CDROM #ifdef HAVE_SOLARIS_CDROM
static const char _rcsid[] = "$Id: _cdio_sunos.c,v 1.12 2003/04/22 12:09:09 rocky Exp $"; static const char _rcsid[] = "$Id: _cdio_sunos.c,v 1.13 2003/05/16 07:18:27 rocky Exp $";
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
@@ -473,13 +473,14 @@ _cdio_eject_media (void *user_data) {
_img_private_t *_obj = user_data; _img_private_t *_obj = user_data;
int ret; int ret;
close(_obj->gen.fd);
_obj->gen.fd = -1;
if (_obj->gen.fd > -1) { if (_obj->gen.fd > -1) {
if ((ret = ioctl(_obj->gen.fd, CDROMEJECT)) != 0) { if ((ret = ioctl(_obj->gen.fd, CDROMEJECT)) != 0) {
cdio_generic_free((void *) _obj); cdio_generic_free((void *) _obj);
cdio_error ("CDROMEJECT failed: %s\n", strerror(errno)); cdio_error ("CDROMEJECT failed: %s\n", strerror(errno));
return 1; return 1;
} else { } else {
cdio_generic_free((void *) _obj);
return 0; return 0;
} }
} }

View File

@@ -1,5 +1,5 @@
/* /*
$Id: cdio.c,v 1.11 2003/04/22 12:09:09 rocky Exp $ $Id: cdio.c,v 1.12 2003/05/16 07:18:27 rocky Exp $
Copyright (C) 2003 Rocky Bernstein <rocky@panix.com> Copyright (C) 2003 Rocky Bernstein <rocky@panix.com>
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org> Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
@@ -35,7 +35,7 @@
#include <cdio/logging.h> #include <cdio/logging.h>
#include "cdio_private.h" #include "cdio_private.h"
static const char _rcsid[] = "$Id: cdio.c,v 1.11 2003/04/22 12:09:09 rocky Exp $"; static const char _rcsid[] = "$Id: cdio.c,v 1.12 2003/05/16 07:18:27 rocky Exp $";
const char *track_format2str[5] = const char *track_format2str[5] =
@@ -135,15 +135,24 @@ CdIo_driver_t CdIo_all_drivers[MAX_DRIVER+1] = {
/*! /*!
Eject media in CD drive if there is a routine to do so. Eject media in CD drive if there is a routine to do so.
Return 0 if success and 1 for failure, and 2 if no routine. Return 0 if success and 1 for failure, and 2 if no routine.
If the CD is ejected *obj is freed and obj set to NULL.
*/ */
int int
cdio_eject_media (const CdIo *obj) cdio_eject_media (CdIo **obj)
{ {
cdio_assert (obj != NULL);
if (obj->op.eject_media) { if ((obj == NULL) || (*obj != NULL)) return 1;
return obj->op.eject_media (obj->user_data);
if ((*obj)->op.eject_media) {
int ret = (*obj)->op.eject_media ((*obj)->user_data);
if (0 == ret) {
cdio_destroy(*obj);
obj = NULL;
}
return ret;
} else { } else {
cdio_destroy(*obj);
obj = NULL;
return 2; return 2;
} }
} }

View File

@@ -23,3 +23,7 @@ cueparser: lex.cue.o cue.tab.o
cuelexer: lex.cuelex.o cuelexer: lex.cuelex.o
gcc -g lex.cuelex.o -lfl -o cuelexer gcc -g lex.cuelex.o -lfl -o cuelexer
clean:
rm -f lex.cue.c lex.cuelex.c lex.cue.o lex.cuelex.o cue.tab.c \
cue.tab.o cueparser cuelexer