Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

cdrdao no-disc ejection & --eject #93

Merged
merged 4 commits into from
Jan 1, 2017
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 7 additions & 9 deletions morituri/command/cd.py
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@
from morituri.common import (
accurip, common, config, drive, gstreamer, program, task
)
from morituri.program import cdrdao, cdparanoia
from morituri.program import cdrdao, cdparanoia, utils
from morituri.result import result

import logging
Expand Down Expand Up @@ -108,8 +108,8 @@ def do(self):
self.device = self.options.device
sys.stdout.write('Checking device %s\n' % self.device)

self.program.loadDevice(self.device)
self.program.unmountDevice(self.device)
utils.load_device(self.device)
utils.unmount_device(self.device)

# first, read the normal TOC, which is fast
self.ittoc = self.program.getFastToc(self.runner,
Expand Down Expand Up @@ -140,8 +140,8 @@ def do(self):

# also used by rip cd info
if not getattr(self.options, 'unknown', False):
if self.eject:
self.program.ejectDevice(self.device)
logger.critical("unable to retrieve disc metadata, "
"--unknown not passed")
return -1

# FIXME ?????
Expand Down Expand Up @@ -205,8 +205,8 @@ def do(self):

self.doCommand()

if self.eject:
self.program.ejectDevice(self.device)
if self.options.eject in ('success', 'always'):
utils.eject_device(self.device)

def doCommand(self):
pass
Expand Down Expand Up @@ -587,8 +587,6 @@ def writeFile(handle, path, length):
# write log file
self.program.writeLog(discName, self.logger)

self.program.ejectDevice(self.device)


class CD(BaseCommand):
summary = "handle CDs"
Expand Down
13 changes: 11 additions & 2 deletions morituri/command/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
from morituri.common import common, directory
from morituri.configure import configure
from morituri.extern.task import task
from morituri.program.utils import eject_device

import logging
logger = logging.getLogger(__name__)
Expand All @@ -25,9 +26,13 @@ def main():
)
map(pkg_resources.working_set.add, distributions)
try:
ret = Whipper(sys.argv[1:], os.path.basename(sys.argv[0]), None).do()
cmd = Whipper(sys.argv[1:], os.path.basename(sys.argv[0]), None)
ret = cmd.do()
except SystemError, e:
sys.stderr.write('whipper: error: %s\n' % e.args)
sys.stderr.write('whipper: error: %s\n' % e)
if (type(e) is common.EjectError and
cmd.options.eject in ('failure', 'always')):
eject_device(e.device)
return 255
except ImportError, e:
raise ImportError(e)
Expand Down Expand Up @@ -76,6 +81,10 @@ def add_arguments(self):
self.parser.add_argument('-h', '--help',
action="store_true", dest="help",
help="show this help message and exit")
self.parser.add_argument('-e', '--eject',
action="store", dest="eject", default="always",
choices=('never', 'failure', 'success', 'always'),
help="when to eject disc (default: always)")

def handle_arguments(self):
if self.options.help:
Expand Down
6 changes: 3 additions & 3 deletions morituri/command/offset.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@
from morituri.command.basecommand import BaseCommand
from morituri.common import accurip, common, config, drive, program
from morituri.common import task as ctask
from morituri.program import cdrdao, cdparanoia
from morituri.program import cdrdao, cdparanoia, utils

from morituri.extern.task import task

Expand Down Expand Up @@ -88,8 +88,8 @@ def do(self):
# if necessary, load and unmount
sys.stdout.write('Checking device %s\n' % device)

prog.loadDevice(device)
prog.unmountDevice(device)
utils.load_device(device)
utils.unmount_device(device)

# first get the Table Of Contents of the CD
t = cdrdao.ReadTOCTask(device)
Expand Down
13 changes: 13 additions & 0 deletions morituri/common/common.py
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,19 @@
BYTES_PER_FRAME = SAMPLES_PER_FRAME * 4


class EjectError(SystemError):
"""
Possibly ejects the drive in command.main.
"""
def __init__(self, device, *args):
"""
args is a tuple used by BaseException.__str__
device is the device path to eject
"""
self.args = args
self.device = device


def msfToFrames(msf):
"""
Converts a string value in MM:SS:FF to frames.
Expand Down
26 changes: 0 additions & 26 deletions morituri/common/program.py
Original file line number Diff line number Diff line change
Expand Up @@ -90,32 +90,6 @@ def setWorkingDirectory(self, workingDirectory):
logger.info('Changing to working directory %s' % workingDirectory)
os.chdir(workingDirectory)

def loadDevice(self, device):
"""
Load the given device.
"""
os.system('eject -t %s' % device)

def ejectDevice(self, device):
"""
Eject the given device.
"""
os.system('eject %s' % device)

def unmountDevice(self, device):
"""
Unmount the given device if it is mounted, as happens with automounted
data tracks.

If the given device is a symlink, the target will be checked.
"""
device = os.path.realpath(device)
logger.debug('possibly unmount real path %r' % device)
proc = open('/proc/mounts').read()
if device in proc:
print 'Device %s is mounted, unmounting' % device
os.system('umount %s' % device)

def getFastToc(self, runner, toc_pickle, device):
"""
Retrieve the normal TOC table from a toc pickle or the drive.
Expand Down
21 changes: 14 additions & 7 deletions morituri/program/cdrdao.py
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
import os
import re
import tempfile
from subprocess import check_call, Popen, PIPE, CalledProcessError
from subprocess import Popen, PIPE

from morituri.common.common import EjectError
from morituri.image.toc import TocFile

import logging
Expand All @@ -27,12 +28,18 @@ def read_toc(device, fast_toc=False):
cmd = [CDRDAO, 'read-toc'] + (['--fast-toc'] if fast_toc else []) + [
'--device', device, tocfile]
# PIPE is the closest to >/dev/null we can get
try:
check_call(cmd, stdout=PIPE, stderr=PIPE)
except CalledProcessError, e:
logger.warning('cdrdao read-toc failed: return code is non-zero: ' +
str(e.returncode))
raise e
logger.debug("executing %r", cmd)
p = Popen(cmd, stdout=PIPE, stderr=PIPE)
_, stderr = p.communicate()
if p.returncode != 0:
msg = 'cdrdao read-toc failed: return code is non-zero: ' + \
str(p.returncode)
logger.critical(msg)
# Gracefully handle missing disc
if "ERROR: Unit not ready, giving up." in stderr:
raise EjectError(device, "no disc detected")
raise IOError(msg)

toc = TocFile(tocfile)
toc.parse()
os.unlink(tocfile)
Expand Down
35 changes: 35 additions & 0 deletions morituri/program/utils.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
import os

import logging
logger = logging.getLogger(__name__)


def eject_device(device):
"""
Eject the given device.
"""
logger.debug("ejecting device %s", device)
os.system('eject %s' % device)


def load_device(device):
"""
Load the given device.
"""
logger.debug("loading (eject -t) device %s", device)
os.system('eject -t %s' % device)


def unmount_device(device):
"""
Unmount the given device if it is mounted, as happens with automounted
data tracks.

If the given device is a symlink, the target will be checked.
"""
device = os.path.realpath(device)
logger.debug('possibly unmount real path %r' % device)
proc = open('/proc/mounts').read()
if device in proc:
print 'Device %s is mounted, unmounting' % device
os.system('umount %s' % device)