Ejemplo n.º 1
0
def read_toc(device, fast_toc=False):
    """
    Return cdrdao-generated table of contents for 'device'.
    """
    # cdrdao MUST be passed a non-existing filename as its last argument
    # to write the TOC to; it does not support writing to stdout or
    # overwriting an existing file, nor does linux seem to support
    # locking a non-existant file. Thus, this race-condition introducing
    # hack is carried from morituri to whipper and will be removed when
    # cdrdao is fixed.
    fd, tocfile = tempfile.mkstemp(suffix=u'.cdrdao.read-toc.whipper')
    os.close(fd)
    os.unlink(tocfile)

    cmd = [CDRDAO, 'read-toc'] + (['--fast-toc'] if fast_toc else
                                  []) + ['--device', device, tocfile]
    # PIPE is the closest to >/dev/null we can get
    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)
    return toc
Ejemplo n.º 2
0
def read_toc(device, fast_toc=False):
    """
    Return cdrdao-generated table of contents for 'device'.
    """
    # cdrdao MUST be passed a non-existing filename as its last argument
    # to write the TOC to; it does not support writing to stdout or
    # overwriting an existing file, nor does linux seem to support
    # locking a non-existant file. Thus, this race-condition introducing
    # hack is carried from morituri to whipper and will be removed when
    # cdrdao is fixed.
    fd, tocfile = tempfile.mkstemp(suffix=u'.cdrdao.read-toc.whipper')
    os.close(fd)
    os.unlink(tocfile)

    cmd = [CDRDAO, 'read-toc'] + (['--fast-toc'] if fast_toc else []) + [
        '--device', device, tocfile]
    # PIPE is the closest to >/dev/null we can get
    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)
    return toc
Ejemplo n.º 3
0
 def _done(self):
     self.setProgress(1.0)
     self.toc = TocFile(self.tocfile)
     self.toc.parse()
     if self.toc_path is not None:
         t_comp = os.path.abspath(self.toc_path).split(os.sep)
         t_dirn = os.sep.join(t_comp[:-1])
         # If the output path doesn't exist, make it recursively
         os.makedirs(t_dirn, exist_ok=True)
         t_dst = truncate_filename(os.path.join(t_dirn,
                                                t_comp[-1] + '.toc'))
         shutil.copy(self.tocfile, os.path.join(t_dirn, t_dst))
     os.unlink(self.tocfile)
     self.stop()
     return
Ejemplo n.º 4
0
 def _done(self):
     self.setProgress(1.0)
     self.toc = TocFile(self.tocfile)
     self.toc.parse()
     if self.toc_path is not None:
         t_comp = os.path.abspath(self.toc_path).split(os.sep)
         t_dirn = os.sep.join(t_comp[:-1])
         # If the output path doesn't exist, make it recursively
         try:
             os.makedirs(t_dirn)
             logger.info("creating output directory %s", t_dirn)
         except FileExistsError as e:
             logger.debug(e)
         t_dst = truncate_filename(os.path.join(t_dirn,
                                                t_comp[-1] + '.toc'))
         shutil.copy(self.tocfile, os.path.join(t_dirn, t_dst))
     os.unlink(self.tocfile)
     self.stop()
     return
Ejemplo n.º 5
0
class ReadTOCTask(task.Task):
    """
    Task that reads the TOC of the disc using cdrdao
    """
    description = "Reading TOC"
    toc = None

    def __init__(self, device, fast_toc=False, toc_path=None):
        """
        Read the TOC for 'device'.

        :param device:  block device to read TOC from
        :type  device:  str
        :param fast_toc:  If to use fast-toc cdrdao mode
        :type  fast_toc: bool
        :param toc_path: Where to save TOC if wanted.
        :type  toc_path: str
        """

        self.device = device
        self.fast_toc = fast_toc
        self.toc_path = toc_path
        self._buffer = ""  # accumulate characters
        self._parser = ProgressParser()

        self.fd, self.tocfile = tempfile.mkstemp(
            suffix='.cdrdao.read-toc.whipper.task')

    def start(self, runner):
        task.Task.start(self, runner)
        os.close(self.fd)
        os.unlink(self.tocfile)

        cmd = ([CDRDAO, 'read-toc'] +
               (['--fast-toc'] if self.fast_toc else []) +
               ['--device', self.device, self.tocfile])

        self._popen = asyncsub.Popen(cmd,
                                     bufsize=1024,
                                     stdin=subprocess.PIPE,
                                     stdout=subprocess.PIPE,
                                     stderr=subprocess.PIPE,
                                     close_fds=True)

        self.schedule(0.01, self._read, runner)

    def _read(self, runner):
        ret = self._popen.recv_err()
        if not ret:
            if self._popen.poll() is not None:
                self._done()
                return
            self.schedule(0.01, self._read, runner)
            return
        self._buffer += ret.decode()

        # parse buffer into lines if possible, and parse them
        if "\n" in self._buffer:
            lines = self._buffer.split('\n')
            if lines[-1] != "\n":
                # last line didn't end yet
                self._buffer = lines[-1]
                del lines[-1]
            else:
                self._buffer = ""
            for line in lines:
                self._parser.parse(line)
                if (self._parser.currentTrack != 0
                        and self._parser.tracks != 0):
                    progress = (float('%d' % self._parser.currentTrack) /
                                float(self._parser.tracks))
                    if progress < 1.0:
                        self.setProgress(progress)

        # 0 does not give us output before we complete, 1.0 gives us output
        # too late
        self.schedule(0.01, self._read, runner)

    def _poll(self, runner):
        if self._popen.poll() is None:
            self.schedule(1.0, self._poll, runner)
            return

        self._done()

    def _done(self):
        self.setProgress(1.0)
        self.toc = TocFile(self.tocfile)
        self.toc.parse()
        if self.toc_path is not None:
            t_comp = os.path.abspath(self.toc_path).split(os.sep)
            t_dirn = os.sep.join(t_comp[:-1])
            # If the output path doesn't exist, make it recursively
            os.makedirs(t_dirn, exist_ok=True)
            t_dst = truncate_filename(os.path.join(t_dirn,
                                                   t_comp[-1] + '.toc'))
            shutil.copy(self.tocfile, os.path.join(t_dirn, t_dst))
        os.unlink(self.tocfile)
        self.stop()
        return