Module refinery.units.formats.archive.xtiso

Expand source code Browse git
from __future__ import annotations

from refinery.lib.iso import FileSystemType, ISOArchive
from refinery.lib.types import Param
from refinery.units.formats.archive import ArchiveUnit, Arg


class xtiso(ArchiveUnit, docs='{0}{p}{PathExtractorUnit}'):
    """
    Extract files from a ISO archive.
    """
    def __init__(
        self, *paths,
        fs: Param[str, Arg.Option('-s', metavar='TYPE', choices=FileSystemType, help=(
            'Specify a file system ({choices}) extension to use. The default setting {default} will automatically '
            'detect the first of the other available options and use it.'))] = 'auto',
        **kwargs
    ):
        super().__init__(*paths, fs=Arg.AsOption(fs, FileSystemType), **kwargs)

    def unpack(self, data):
        if not self.handles(data):
            self.log_warn('The data does not look like an ISO file.')
        iso = ISOArchive(data)
        if (fs := self.args.fs) != FileSystemType.AUTO:
            iso.select_filesystem(fs)
        self.log_info(F'using format: {iso.filesystem_type}')
        for entry in iso.entries():
            def extract(e=entry):
                return iso.extract(e)
            yield self._pack(entry.path, entry.date, extract)

    @classmethod
    def handles(cls, data) -> bool:
        return any(data[k] == B'CD001' for k in (
            slice(0x8001, 0x8006),
            slice(0x8801, 0x8806),
            slice(0x9001, 0x9006),
        ))

Classes

class xtiso (*paths, fs='auto', pwd=b'', date=b'date', exclude=None, path=b'path', regex=False, exact=False, fuzzy=0, drop_path=False, join_path=False, list=False)

Extract files from a ISO archive.

This unit extracts items with an associated virtual path from a container; each extracted item is emitted as a separate chunk with a corresponding meta variable named "path".

Positional arguments to xtiso are patterns to filter the extracted items. Use the -x flag to add an exclusion pattern. To extract all files with a foo or bar extension, but none that has the word "temp" in its path:

xtiso .foo .bar -x temp

To view only the paths of all chunks, use the listing switch:

emit data | ... | xtiso -l

Otherwise, extracted items are written to the standard output port and usually require a frame to properly process. In order to dump all extracted data to disk, the following pipeline can be used:

emit data | ... | xtiso [| dump extracted/{path} ]

The value {path} is a placeholder which is substituted by the virtual path of the extracted item. When using xtiso to unpack a file on disk, the following pattern can be useful:

ef pack.bin [| xtiso -j | d2p ]

The unit ef is also a path extractor. By specifying -j (or --join), the paths of extracted items are combined. Here, d2p is a shortcut for dump {path}. It deconflicts the joined paths with the local file system: If pack.bin contains items one.txt and two.txt, the following local file tree would be the result:

pack.bin
pack/one.txt
pack/two.txt

Finally, the -d (or --drop) switch can be used to not create (or alter) the path metadata at all, which is useful in cases where path metadata from a previous unit should be preserved.

Expand source code Browse git
class xtiso(ArchiveUnit, docs='{0}{p}{PathExtractorUnit}'):
    """
    Extract files from a ISO archive.
    """
    def __init__(
        self, *paths,
        fs: Param[str, Arg.Option('-s', metavar='TYPE', choices=FileSystemType, help=(
            'Specify a file system ({choices}) extension to use. The default setting {default} will automatically '
            'detect the first of the other available options and use it.'))] = 'auto',
        **kwargs
    ):
        super().__init__(*paths, fs=Arg.AsOption(fs, FileSystemType), **kwargs)

    def unpack(self, data):
        if not self.handles(data):
            self.log_warn('The data does not look like an ISO file.')
        iso = ISOArchive(data)
        if (fs := self.args.fs) != FileSystemType.AUTO:
            iso.select_filesystem(fs)
        self.log_info(F'using format: {iso.filesystem_type}')
        for entry in iso.entries():
            def extract(e=entry):
                return iso.extract(e)
            yield self._pack(entry.path, entry.date, extract)

    @classmethod
    def handles(cls, data) -> bool:
        return any(data[k] == B'CD001' for k in (
            slice(0x8001, 0x8006),
            slice(0x8801, 0x8806),
            slice(0x9001, 0x9006),
        ))

Ancestors

Subclasses

Class variables

var reverse

The type of the None singleton.

Methods

def unpack(self, data)
Expand source code Browse git
def unpack(self, data):
    if not self.handles(data):
        self.log_warn('The data does not look like an ISO file.')
    iso = ISOArchive(data)
    if (fs := self.args.fs) != FileSystemType.AUTO:
        iso.select_filesystem(fs)
    self.log_info(F'using format: {iso.filesystem_type}')
    for entry in iso.entries():
        def extract(e=entry):
            return iso.extract(e)
        yield self._pack(entry.path, entry.date, extract)

Inherited members