* Umount before ejecting
* Ultra simple eject command
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
# $Id: Makefile.am,v 1.38 2006/10/11 12:38:18 rocky Exp $
|
||||
# $Id: Makefile.am,v 1.39 2006/10/21 10:55:18 gmerlin Exp $
|
||||
#
|
||||
# Copyright (C) 2003, 2004, 2005, 2006
|
||||
# Rocky Bernstein <rocky@cpan.org>
|
||||
@@ -30,7 +30,7 @@ endif
|
||||
noinst_PROGRAMS = audio cdchange cdtext device drives eject \
|
||||
isofile isofile2 isofuzzy isolist \
|
||||
mmc1 mmc2 mmc2a mmc3 $(paranoia_progs) tracks \
|
||||
sample3 sample4 udf1 udffile
|
||||
sample3 sample4 udf1 udffile cdio-eject
|
||||
|
||||
INCLUDES = -I$(top_srcdir) $(LIBCDIO_CFLAGS)
|
||||
|
||||
@@ -52,6 +52,9 @@ drives_LDADD = $(LIBCDIO_LIBS)
|
||||
eject_DEPENDENCIES = $(LIBCDIO_DEPS)
|
||||
eject_LDADD = $(LIBCDIO_LIBS)
|
||||
|
||||
cdio_eject_DEPENDENCIES = $(LIBCDIO_DEPS)
|
||||
cdio_eject_LDADD = $(LIBCDIO_LIBS)
|
||||
|
||||
if BUILD_CD_PARANOIA
|
||||
paranoia_LDADD = $(LIBCDIO_PARANOIA_LIBS) $(LIBCDIO_CDDA_LIBS) $(LIBCDIO_LIBS)
|
||||
paranoia2_LDADD = $(LIBCDIO_PARANOIA_LIBS) $(LIBCDIO_CDDA_LIBS) $(LIBCDIO_LIBS)
|
||||
|
||||
59
example/cdio-eject.c
Normal file
59
example/cdio-eject.c
Normal file
@@ -0,0 +1,59 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <cdio/cdio.h>
|
||||
|
||||
static void usage(char * progname)
|
||||
{
|
||||
fprintf(stderr, "Usage: %s [-t] <device>\n", progname);
|
||||
}
|
||||
|
||||
int main(int argc, char ** argv)
|
||||
{
|
||||
driver_return_code_t err;
|
||||
int close_tray = 0;
|
||||
const char * device = NULL;
|
||||
|
||||
if(argc < 2 || argc > 3)
|
||||
{
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if((argc == 3) && strcmp(argv[1], "-t"))
|
||||
{
|
||||
usage(argv[0]);
|
||||
return -1;
|
||||
}
|
||||
|
||||
if(argc == 2)
|
||||
device = argv[1];
|
||||
else if(argc == 3)
|
||||
{
|
||||
close_tray = 1;
|
||||
device = argv[2];
|
||||
}
|
||||
|
||||
if(close_tray)
|
||||
{
|
||||
err = cdio_close_tray(device, NULL);
|
||||
if(err)
|
||||
{
|
||||
fprintf(stderr, "Closing tray failed for device %s: %s\n",
|
||||
device, cdio_driver_errmsg(err));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
err = cdio_eject_media_drive(device);
|
||||
if(err)
|
||||
{
|
||||
fprintf(stderr, "Ejecting failed for device %s: %s\n",
|
||||
device, cdio_driver_errmsg(err));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
$Id: gnu_linux.c,v 1.24 2006/08/02 11:00:31 rocky Exp $
|
||||
$Id: gnu_linux.c,v 1.25 2006/10/21 10:55:18 gmerlin Exp $
|
||||
|
||||
Copyright (C) 2001 Herbert Valerio Riedel <hvr@gnu.org>
|
||||
Copyright (C) 2002, 2003, 2004, 2005, 2006 Rocky Bernstein
|
||||
@@ -28,9 +28,12 @@
|
||||
# include "config.h"
|
||||
#endif
|
||||
|
||||
static const char _rcsid[] = "$Id: gnu_linux.c,v 1.24 2006/08/02 11:00:31 rocky Exp $";
|
||||
static const char _rcsid[] = "$Id: gnu_linux.c,v 1.25 2006/10/21 10:55:18 gmerlin Exp $";
|
||||
|
||||
#include <string.h>
|
||||
#include <limits.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/wait.h>
|
||||
|
||||
#include <cdio/sector.h>
|
||||
#include <cdio/util.h>
|
||||
@@ -592,6 +595,107 @@ get_track_msf_linux(void *p_user_data, track_t i_track, msf_t *msf)
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Follow symlinks until we have the real device file
|
||||
(idea taken from libunieject).
|
||||
*/
|
||||
|
||||
static void follow_symlink (const char * src, char * dst) {
|
||||
char tmp_src[PATH_MAX];
|
||||
char tmp_dst[PATH_MAX];
|
||||
|
||||
int len;
|
||||
|
||||
strcpy(tmp_src, src);
|
||||
while(1) {
|
||||
len = readlink(tmp_src, tmp_dst, PATH_MAX);
|
||||
if(len < 0) {
|
||||
strcpy(dst, tmp_src);
|
||||
return;
|
||||
}
|
||||
else {
|
||||
tmp_dst[len] = '\0';
|
||||
strcpy(tmp_src, tmp_dst);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*!
|
||||
Check, if a device is mounted and return the target (=mountpoint)
|
||||
needed for umounting (idea taken from libunieject).
|
||||
*/
|
||||
|
||||
static int is_mounted (const char * device, char * target) {
|
||||
FILE * fp;
|
||||
char real_device_1[PATH_MAX];
|
||||
char real_device_2[PATH_MAX];
|
||||
|
||||
char file_device[PATH_MAX];
|
||||
char file_target[PATH_MAX];
|
||||
|
||||
fp = fopen ( "/proc/mounts", "r");
|
||||
/* Older systems just have /etc/mtab */
|
||||
if(!fp)
|
||||
fp = fopen ( "/etc/mtab", "r");
|
||||
|
||||
/* Neither /proc/mounts nor /etc/mtab could be opened, give up here */
|
||||
if(!fp) return 0;
|
||||
|
||||
/* Get real device */
|
||||
follow_symlink(device, real_device_1);
|
||||
|
||||
/* Read entries */
|
||||
|
||||
while ( fscanf(fp, "%s %s %*s %*s %*d %*d\n", file_device, file_target) != EOF ) {
|
||||
follow_symlink(file_device, real_device_2);
|
||||
if(!strcmp(real_device_1, real_device_2)) {
|
||||
strcpy(target, file_target);
|
||||
fclose(fp);
|
||||
return 1;
|
||||
}
|
||||
|
||||
}
|
||||
fclose(fp);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/*!
|
||||
Umount a filesystem specified by it's mountpoint. We must do this
|
||||
by forking and calling the umount command, because the raw umount
|
||||
(or umount2) system calls will *always* trigger an EPERM even if
|
||||
we are allowed to umount the filesystem. The umount command is
|
||||
suid root.
|
||||
|
||||
Code here is inspired by the standard linux eject command by
|
||||
Jeff Tranter and Frank Lichtenheld.
|
||||
*/
|
||||
|
||||
static int do_umount(char * target) {
|
||||
int status;
|
||||
|
||||
switch (fork()) {
|
||||
case 0: /* child */
|
||||
execlp("pumount", "pumount", target, NULL);
|
||||
execlp("umount", "umount", target, NULL);
|
||||
return -1;
|
||||
break;
|
||||
case -1:
|
||||
return -1;
|
||||
break;
|
||||
default: /* parent */
|
||||
wait(&status);
|
||||
if (WIFEXITED(status) == 0) {
|
||||
return -1;
|
||||
}
|
||||
if (WEXITSTATUS(status) != 0) {
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
/*!
|
||||
Eject media in CD-ROM drive. Return DRIVER_OP_SUCCESS if successful,
|
||||
DRIVER_OP_ERROR on error.
|
||||
@@ -603,10 +707,15 @@ eject_media_linux (void *p_user_data) {
|
||||
_img_private_t *p_env = p_user_data;
|
||||
driver_return_code_t ret=DRIVER_OP_SUCCESS;
|
||||
int status;
|
||||
int was_open = 0;
|
||||
char mount_target[PATH_MAX];
|
||||
|
||||
if ( p_env->gen.fd <= -1 ) {
|
||||
p_env->gen.fd = open (p_env->gen.source_name, O_RDONLY|O_NONBLOCK);
|
||||
}
|
||||
else {
|
||||
was_open = 1;
|
||||
}
|
||||
|
||||
if ( p_env->gen.fd <= -1 ) return DRIVER_OP_ERROR;
|
||||
|
||||
@@ -622,6 +731,23 @@ eject_media_linux (void *p_user_data) {
|
||||
cdio_info ("Unknown state of CD-ROM (%d)\n", status);
|
||||
/* Fall through */
|
||||
case CDS_DISC_OK:
|
||||
/* Some systems automount the drive, so we must umount it.
|
||||
We check if the drive is actually mounted */
|
||||
if(is_mounted (p_env->gen.source_name, mount_target)) {
|
||||
/* Try to umount the drive */
|
||||
if(do_umount(mount_target)) {
|
||||
cdio_log(CDIO_LOG_WARN, "Could not umount %s\n",
|
||||
p_env->gen.source_name);
|
||||
ret=DRIVER_OP_ERROR;
|
||||
break;
|
||||
}
|
||||
/* For some reason, we must close and reopen the device after
|
||||
it got umounted (at least the commandline eject program
|
||||
opens the device just after umounting it) */
|
||||
close(p_env->gen.fd);
|
||||
p_env->gen.fd = open (p_env->gen.source_name, O_RDONLY|O_NONBLOCK);
|
||||
}
|
||||
|
||||
if((ret = ioctl(p_env->gen.fd, CDROMEJECT)) != 0) {
|
||||
int eject_error = errno;
|
||||
/* Try ejecting the MMC way... */
|
||||
@@ -642,7 +768,10 @@ eject_media_linux (void *p_user_data) {
|
||||
cdio_warn ("CDROM_DRIVE_STATUS failed: %s\n", strerror(errno));
|
||||
ret=DRIVER_OP_ERROR;
|
||||
}
|
||||
p_env->gen.fd = -1;
|
||||
if(!was_open) {
|
||||
close(p_env->gen.fd);
|
||||
p_env->gen.fd = -1;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user