Python tarfile.TarError() Examples

The following are 30 code examples of tarfile.TarError(). You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may also want to check out all available functions/classes of the module tarfile , or try the search function .
Example #1
Source File: tar.py    From ingestors with MIT License 7 votes vote down vote up
def unpack(self, file_path, temp_dir):
        try:
            with tarfile.open(name=file_path, mode='r:*') as tf:
                names = tf.getnames()
                encoding = self.detect_list_encoding(names,
                                                     default=tf.encoding)
                log.debug('Detected filename encoding: %s', encoding)

                for name in names:
                    try:
                        fh = tf.extractfile(name)
                        self.extract_member(temp_dir, name, fh,
                                            encoding=encoding)
                    except Exception as ex:
                        # TODO: should this be a fatal error?
                        log.debug("Failed to unpack [%r]: %s", name, ex)
        except (tarfile.TarError, IOError, EOFError) as err:
            raise ProcessingException('Invalid Tar file: %s' % err) 
Example #2
Source File: base.py    From anybox.recipe.odoo with GNU Affero General Public License v3.0 6 votes vote down vote up
def main_download(self):
        """HTTP download for main part of the software to self.archive_path.
        """
        if self.offline:
            raise IOError("%s not found, and offline "
                          "mode requested" % self.archive_path)
        url = self.sources[main_software][1]
        logger.info("Downloading %s ..." % url)

        try:
            msg = urlretrieve(url, self.archive_path)
            if get_content_type(msg[1]) == 'text/html':
                os.unlink(self.archive_path)
                raise LookupError(
                    'Wanted version %r not found on server (tried %s)' % (
                        self.version_wanted, url))

        except (tarfile.TarError, IOError):
            # GR: ContentTooShortError subclasses IOError
            os.unlink(self.archive_path)
            raise IOError('The archive does not seem valid: ' +
                          repr(self.archive_path)) 
Example #3
Source File: main.py    From rucio with Apache License 2.0 6 votes vote down vote up
def GET(self):
        try:
            data = param_input()
            response = get(str(data.file_location), cert=config_get('webui', 'usercert'), verify=False)
            if not response.ok:
                response.raise_for_status()
            cont = response.content
            file_like_object = BytesIO(cont)
            tar = open(mode='r:gz', fileobj=file_like_object)
            jsonResponse = {}
            for member in tar.getmembers():
                jsonResponse[member.name] = member.size
            header('Content-Type', 'application/json')
            return dumps(jsonResponse)
        except ConnectionError as err:
            raise generate_http_error(503, str(type(err)), str(err))
        except TarError as err:
            raise generate_http_error(415, str(type(err)), str(err))
        except IOError as err:
            raise generate_http_error(422, str(type(err)), str(err))
        except Exception as err:
            raise generate_http_error(500, str(type(err)), str(err)) 
Example #4
Source File: download.py    From cornac with Apache License 2.0 6 votes vote down vote up
def _extract_archive(file_path, extract_path="."):
    """Extracts an archive.
    """
    for archive_type in ["zip", "tar"]:
        if archive_type == "zip":
            open_fn = zipfile.ZipFile
            is_match_fn = zipfile.is_zipfile
        elif archive_type == "tar":
            open_fn = tarfile.open
            is_match_fn = tarfile.is_tarfile

        if is_match_fn(file_path):
            with open_fn(file_path) as archive:
                try:
                    archive.extractall(extract_path)
                except (tarfile.TarError, RuntimeError, KeyboardInterrupt):
                    if os.path.exists(extract_path):
                        if os.path.isfile(extract_path):
                            os.remove(extract_path)
                        else:
                            shutil.rmtree(extract_path)
                    raise 
Example #5
Source File: utils.py    From substra-backend with Apache License 2.0 6 votes vote down vote up
def uncompress_content(archive_content, to_directory):
    if zipfile.is_zipfile(io.BytesIO(archive_content)):
        with ZipFile(io.BytesIO(archive_content)) as zf:

            # Check no path traversal
            filenames = [os.path.join(to_directory, filename)
                         for filename in zf.namelist()]
            raise_if_path_traversal(filenames, to_directory)

            zf.extractall(to_directory)
    else:
        try:
            with tarfile.open(fileobj=io.BytesIO(archive_content)) as tf:

                # Check no path traversal
                filenames = [os.path.join(to_directory, filename)
                             for filename in tf.getnames()]
                raise_if_path_traversal(filenames, to_directory)

                tf.extractall(to_directory)
        except tarfile.TarError:
            raise Exception('Archive must be zip or tar.*') 
Example #6
Source File: remotes.py    From syntribos with Apache License 2.0 6 votes vote down vote up
def get(uri, cache_dir=None):
    """Entry method for download method

    :param str uri: A formatted remote URL of a file
    :param str: Absolute path to the downloaded content
    :param str cache_dir: path to save downloaded files
    """
    user_base_dir = cache_dir or CONF.remote.cache_dir
    if user_base_dir:
        try:
            temp = tempfile.TemporaryFile(dir=os.path.abspath(user_base_dir))
            temp.close()
        except OSError:
            LOG.error("Failed to write remote files to: %s",
                      os.path.abspath(user_base_dir))
            exit(1)
        abs_path = download(uri, os.path.abspath(user_base_dir))
    else:
        abs_path = download(uri)
    try:
        return extract_tar(abs_path)
    except (tarfile.TarError, Exception):
        msg = _("Not a gz file, returning abs_path")
        LOG.debug(msg)
        return abs_path 
Example #7
Source File: vcs.py    From temci with GNU General Public License v3.0 6 votes vote down vote up
def copy_revision(self, id_or_num: t.Union[int, str], sub_dir: str, dest_dirs: t.List[str]):
        typecheck_locals(id_or_num=self.id_type, dest_dirs=List(Str())|Str())
        if isinstance(dest_dirs, str):
            dest_dirs = [dest_dirs]
        if id_or_num == -1 or id_or_num == "HEAD":
            self._copy_dir(sub_dir, dest_dirs)
        sub_dir = os.path.join(self.base_path, sub_dir)
        tar_file = os.path.abspath(os.path.join(Settings()["tmp_dir"], "tmp.tar"))
        cmd = "git archive --format tar --output {} {}".format(tar_file, self._commit_number_to_id(id_or_num))
        self._exec_command(cmd)
        try:
            with tarfile.open(tar_file) as tar:
                for dest in dest_dirs:
                    if sub_dir == ".":
                        tar.extractall(os.path.abspath(dest))
                    else:
                        subdir_and_files = [
                                tarinfo for tarinfo in tar.getmembers() if tarinfo.name.startswith(sub_dir + "/") or tarinfo.name is sub_dir
                            ]
                        tar.extractall(members=subdir_and_files, path=os.path.abspath(dest))
        except tarfile.TarError as err:
            os.remove(tar_file)
            raise VCSError(str(err))
        os.remove(tar_file) 
Example #8
Source File: archive.py    From bob with GNU General Public License v3.0 6 votes vote down vote up
def _uploadPackage(self, buildId, suffix, audit, content):
        # Set default signal handler so that KeyboardInterrupt is raised.
        # Needed to gracefully handle ctrl+c.
        signal.signal(signal.SIGINT, signal.default_int_handler)

        try:
            with self._openUploadFile(buildId, suffix) as (name, fileobj):
                pax = { 'bob-archive-vsn' : "1" }
                with gzip.open(name or fileobj, 'wb', 6) as gzf:
                    with tarfile.open(name, "w", fileobj=gzf,
                                      format=tarfile.PAX_FORMAT, pax_headers=pax) as tar:
                        tar.add(audit, "meta/" + os.path.basename(audit))
                        tar.add(content, arcname="content")
        except ArtifactExistsError:
            return ("skipped ({} exists in archive)".format(content), SKIPPED)
        except (ArtifactUploadError, tarfile.TarError, OSError) as e:
            if self.__ignoreErrors:
                return ("error ("+str(e)+")", ERROR)
            else:
                raise BuildError("Cannot upload artifact: " + str(e))
        finally:
            # Restore signals to default so that Ctrl+C kills process. Needed
            # to prevent ugly backtraces when user presses ctrl+c.
            signal.signal(signal.SIGINT, signal.SIG_DFL)
        return ("ok", EXECUTED) 
Example #9
Source File: archive_util.py    From pledgeservice with Apache License 2.0 5 votes vote down vote up
def unpack_tarfile(filename, extract_dir, progress_filter=default_filter):
    """Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir`

    Raises ``UnrecognizedFormat`` if `filename` is not a tarfile (as determined
    by ``tarfile.open()``).  See ``unpack_archive()`` for an explanation
    of the `progress_filter` argument.
    """
    try:
        tarobj = tarfile.open(filename)
    except tarfile.TarError:
        raise UnrecognizedFormat(
            "%s is not a compressed or uncompressed tar file" % (filename,)
        )
    try:
        tarobj.chown = lambda *args: None   # don't do any chowning!
        for member in tarobj:
            name = member.name
            # don't extract absolute paths or ones with .. in them
            if not name.startswith('/') and '..' not in name.split('/'):
                prelim_dst = os.path.join(extract_dir, *name.split('/'))

                # resolve any links and to extract the link targets as normal files
                while member is not None and (member.islnk() or member.issym()):
                    linkpath = member.linkname
                    if member.issym():
                        linkpath = posixpath.join(posixpath.dirname(member.name), linkpath)
                        linkpath = posixpath.normpath(linkpath)
                    member = tarobj._getmember(linkpath)

                if member is not None and (member.isfile() or member.isdir()):
                    final_dst = progress_filter(name, prelim_dst)
                    if final_dst:
                        if final_dst.endswith(os.sep):
                            final_dst = final_dst[:-1]
                        try:
                            tarobj._extract_member(member, final_dst)  # XXX Ugh
                        except tarfile.ExtractError:
                            pass    # chown/chmod/mkfifo/mknode/makedev failed
        return True
    finally:
        tarobj.close() 
Example #10
Source File: package.py    From crypto with MIT License 5 votes vote down vote up
def _generate_tar(dir_path):
    """Private function that reads a local directory and generates a tar archive from it"""
    try:
        with tarfile.open(dir_path + '.tar', 'w') as tar:
            tar.add(dir_path)
    except tarfile.TarError as e:
        stderr("Error: tar archive creation failed [" + str(e) + "]", exit=1) 
Example #11
Source File: archive_util.py    From oss-ftp with MIT License 5 votes vote down vote up
def unpack_tarfile(filename, extract_dir, progress_filter=default_filter):
    """Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir`

    Raises ``UnrecognizedFormat`` if `filename` is not a tarfile (as determined
    by ``tarfile.open()``).  See ``unpack_archive()`` for an explanation
    of the `progress_filter` argument.
    """
    try:
        tarobj = tarfile.open(filename)
    except tarfile.TarError:
        raise UnrecognizedFormat(
            "%s is not a compressed or uncompressed tar file" % (filename,)
        )
    with contextlib.closing(tarobj):
        tarobj.chown = lambda *args: None   # don't do any chowning!
        for member in tarobj:
            name = member.name
            # don't extract absolute paths or ones with .. in them
            if not name.startswith('/') and '..' not in name.split('/'):
                prelim_dst = os.path.join(extract_dir, *name.split('/'))

                # resolve any links and to extract the link targets as normal files
                while member is not None and (member.islnk() or member.issym()):
                    linkpath = member.linkname
                    if member.issym():
                        linkpath = posixpath.join(posixpath.dirname(member.name), linkpath)
                        linkpath = posixpath.normpath(linkpath)
                    member = tarobj._getmember(linkpath)

                if member is not None and (member.isfile() or member.isdir()):
                    final_dst = progress_filter(name, prelim_dst)
                    if final_dst:
                        if final_dst.endswith(os.sep):
                            final_dst = final_dst[:-1]
                        try:
                            tarobj._extract_member(member, final_dst)  # XXX Ugh
                        except tarfile.ExtractError:
                            pass    # chown/chmod/mkfifo/mknode/makedev failed
        return True 
Example #12
Source File: tar.py    From blueflower with GNU General Public License v3.0 5 votes vote down vote up
def tar_do_data(data, afile):
    filelike = io.BytesIO(data)
    try:
        atar = tarfile.open(fileobj=filelike)
    except tarfile.TarError as e:
        log_error(str(e), afile)
        return
    tar_do_tar(atar, afile)
    atar.close() 
Example #13
Source File: file_system_metadata.py    From FACT_core with GNU General Public License v3.0 5 votes vote down vote up
def _extract_metadata_from_tar(self, file_object: FileObject):
        try:
            for file_info in tarfile.open(file_object.file_path):
                if file_info.isfile():
                    self._enter_results_for_tar_file(file_info)
        except tarfile.TarError:
            logging.warning('could not open tar archive {}'.format(file_object.file_name))
        except zlib.error:
            logging.warning('could not open compressed tar archive: {}'.format(file_object.file_name))
        except EOFError:
            logging.warning('could not open archive: unexpected EOF {}'.format(file_object.file_name)) 
Example #14
Source File: archive.py    From bob with GNU General Public License v3.0 5 votes vote down vote up
def _downloadPackage(self, buildId, suffix, audit, content):
        # Set default signal handler so that KeyboardInterrupt is raised.
        # Needed to gracefully handle ctrl+c.
        signal.signal(signal.SIGINT, signal.default_int_handler)

        try:
            with self._openDownloadFile(buildId, suffix) as (name, fileobj):
                with tarfile.open(name, "r|*", fileobj=fileobj, errorlevel=1) as tar:
                    removePath(audit)
                    removePath(content)
                    os.makedirs(content)
                    self.__extractPackage(tar, audit, content)
            return (True, None, None)
        except ArtifactNotFoundError:
            return (False, "not found", WARNING)
        except ArtifactDownloadError as e:
            return (False, e.reason, WARNING)
        except BuildError as e:
            raise
        except OSError as e:
            raise BuildError("Cannot download artifact: " + str(e))
        except tarfile.TarError as e:
            raise BuildError("Error extracting binary artifact: " + str(e))
        finally:
            # Restore signals to default so that Ctrl+C kills process. Needed
            # to prevent ugly backtraces when user presses ctrl+c.
            signal.signal(signal.SIGINT, signal.SIG_DFL) 
Example #15
Source File: main.py    From rucio with Apache License 2.0 5 votes vote down vote up
def GET(self):
        try:
            pyDict = {}
            data = param_input()
            response = get(str(data.file_location), cert=config_get('webui', 'usercert'), verify=False)
            if not response.ok:
                response.raise_for_status()
            cont = response.content
            file_like_object = BytesIO(cont)
            tar = open(mode='r:gz', fileobj=file_like_object)
            for member in tar.getmembers():
                if member.name == str(data.file_name):
                    try:
                        f = tar.extractfile(member)
                        pyDict['content'] = f.read(16000000)
                        pyDict['size'] = f.tell()
                        jsonResponse = dumps(pyDict)
                        tar.close()
                        return jsonResponse
                    except UnicodeDecodeError:
                        f = tar.extractfile(member)
                        out = GzipFile(fileobj=f)
                        pyDict['content'] = out.read(16000000)
                        pyDict['size'] = out.tell()
                        jsonResponse = dumps(pyDict)
                        tar.close()
                        return jsonResponse
                    return "ok"
        except ConnectionError as err:
            raise generate_http_error(503, str(type(err)), str(err))
        except TarError as err:
            raise generate_http_error(415, str(type(err)), str(err))
        except IOError as err:
            raise generate_http_error(422, str(type(err)), str(err))
        except Exception as err:
            raise generate_http_error(500, str(type(err)), str(err)) 
Example #16
Source File: mangascrapper.py    From MangaScrapper with Apache License 2.0 5 votes vote down vote up
def _create_cbt_(dirpath, archivename):
        """
        Create a Comic Book Archive in .cbt format (Tar Compression)

        :param dirpath: Directory location to save the the book archive.
        :param archivename: Name of the archive.
        """
        try:
            with tarfile.open(archivename, "w") as tar:
                tar.add(dirpath, arcname=os.path.basename(dirpath))
        except tarfile.TarError:
            logging.error("Unable to create CBT file. Report to Developer.") 
Example #17
Source File: tar.py    From blueflower with GNU General Public License v3.0 5 votes vote down vote up
def tar_do_file(afile):
    try:
        atar = tarfile.open(afile)
    except tarfile.TarError as e:
        log_error(str(e), afile)
        return
    tar_do_tar(atar, afile)
    atar.close() 
Example #18
Source File: shutil.py    From kobo-predict with BSD 2-Clause "Simplified" License 5 votes vote down vote up
def _unpack_tarfile(filename, extract_dir):
    """Unpack tar/tar.gz/tar.bz2/tar.xz `filename` to `extract_dir`
    """
    try:
        tarobj = tarfile.open(filename)
    except tarfile.TarError:
        raise ReadError(
            "%s is not a compressed or uncompressed tar file" % filename)
    try:
        tarobj.extractall(extract_dir)
    finally:
        tarobj.close() 
Example #19
Source File: archive.py    From turbinia with Apache License 2.0 5 votes vote down vote up
def UncompressTarFile(compressed_directory, output_tmp):
  """Uncompress a provided tar file.

  Args:
    compressed_directory(str): The path to the tar file.
    output_tmp(str): The path to the temporary directory that the
                      uncompressed tar file will be placed into.

  Returns:
    str: The path to the uncompressed directory.
  """
  # Tar file validation check
  ValidateTarFile(compressed_directory)

  # Generate the uncompressed directory path
  uncompressed_file = 'uncompressed-' + str(int(time()))
  uncompressed_directory = os.path.join(output_tmp, uncompressed_file)

  # Uncompress the tar file into the uncompressed directory.
  try:
    tar = tarfile.TarFile.open(compressed_directory)
    tar.extractall(path=uncompressed_directory)
    tar.close()
    log.info(
        'The tar file has been uncompressed to the following directory: {0:s}'
        .format(uncompressed_directory))
  except IOError as exception:
    raise TurbiniaException('An error has occurred: {0:s}'.format(exception))
  except tarfile.TarError as exception:
    raise TurbiniaException(
        'An error has occurred while uncompressing the tar '
        'file: {0:s}'.format(exception))
  return uncompressed_directory 
Example #20
Source File: archive.py    From turbinia with Apache License 2.0 5 votes vote down vote up
def CompressDirectory(uncompressed_directory, output_path=None):
  """Compress a given directory into a tar file.

  Args:
    uncompressed_directory(str): The path to the uncompressed directory.
    output_path(str): The path to compress the directory into.

  Returns:
    str: The path to the tar file.
  """
  # Error handling check for a non-existent file or directory.
  if not os.path.exists(uncompressed_directory):
    raise TurbiniaException(
        'The File or Directory does not exist: {0:s}'.format(
            uncompressed_directory))

  # Iterate through a given list of files and compress them.
  compressed_directory = uncompressed_directory + '.tar.gz'
  if output_path:
    output_file = compressed_directory.split('/')[-1]
    compressed_directory = os.path.join(output_path, output_file)
  try:
    with tarfile.TarFile.open(compressed_directory, 'w:gz') as tar:
      tar.add(uncompressed_directory, arcname='')
      tar.close()
      log.info(
          'The tar file has been created and '
          'can be found at: {0:s}'.format(compressed_directory))
  except IOError as exception:
    raise TurbiniaException('An error has occurred: {0:s}'.format(exception))
  except tarfile.TarError as exception:
    raise TurbiniaException(
        'An error has while compressing the directory: {0:s}'.format(exception))
  return compressed_directory 
Example #21
Source File: project.py    From git-repo with Apache License 2.0 5 votes vote down vote up
def _ExtractArchive(self, tarpath, path=None):
    """Extract the given tar on its current location

    Args:
        - tarpath: The path to the actual tar file

    """
    try:
      with tarfile.open(tarpath, 'r') as tar:
        tar.extractall(path=path)
        return True
    except (IOError, tarfile.TarError) as e:
      _error("Cannot extract archive %s: %s", tarpath, str(e))
    return False 
Example #22
Source File: shutil.py    From ironpython3 with Apache License 2.0 5 votes vote down vote up
def _unpack_tarfile(filename, extract_dir):
    """Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir`
    """
    try:
        tarobj = tarfile.open(filename)
    except tarfile.TarError:
        raise ReadError(
            "%s is not a compressed or uncompressed tar file" % filename)
    try:
        tarobj.extractall(extract_dir)
    finally:
        tarobj.close() 
Example #23
Source File: utils.py    From substra-backend with Apache License 2.0 5 votes vote down vote up
def __call__(self, data):

        archive = None
        try:
            data.file.seek(0)
        except Exception:
            raise ValidationError(self.error_messages['open'])
        else:
            try:
                # is tarfile?
                archive = tarfile.open(fileobj=data.file)
            except tarfile.TarError:
                # is zipfile?
                if not zipfile.is_zipfile(data.file):
                    raise ValidationError(self.error_messages['compressed'])

                archive = zipfile.ZipFile(file=data.file)
                self.validate_archive(archive.namelist())
            else:
                self.validate_archive(archive.getnames())
            finally:
                data.file.seek(0)

                if archive:
                    archive.close()
                else:
                    raise ValidationError(self.error_messages['open']) 
Example #24
Source File: datasample.py    From substra-backend with Apache License 2.0 5 votes vote down vote up
def __call__(self, data):

        archive = None

        try:
            data.file.seek(0)
        except Exception:
            raise ValidationError(self.error_messages['open'])
        else:
            try:
                # is tarfile?
                archive = tarfile.open(fileobj=data.file)
            except tarfile.TarError:
                # is zipfile?
                if not zipfile.is_zipfile(data.file):
                    raise ValidationError(self.error_messages['compressed'])

                archive = zipfile.ZipFile(file=data.file)
                self.validate_archive(archive.namelist())
            else:
                self.validate_archive(archive.getnames())
            finally:
                data.file.seek(0)

                if archive:
                    archive.close()
                else:
                    raise ValidationError(self.error_messages['open']) 
Example #25
Source File: io.py    From rasa-for-botfront with Apache License 2.0 5 votes vote down vote up
def unarchive(byte_array: bytes, directory: Text) -> Text:
    """Tries to unpack a byte array interpreting it as an archive.

    Tries to use tar first to unpack, if that fails, zip will be used."""

    try:
        tar = tarfile.open(fileobj=IOReader(byte_array))
        tar.extractall(directory)
        tar.close()
        return directory
    except tarfile.TarError:
        zip_ref = zipfile.ZipFile(IOReader(byte_array))
        zip_ref.extractall(directory)
        zip_ref.close()
        return directory 
Example #26
Source File: shutil.py    From jawfish with MIT License 5 votes vote down vote up
def _unpack_tarfile(filename, extract_dir):
    """Unpack tar/tar.gz/tar.bz2 `filename` to `extract_dir`
    """
    try:
        tarobj = tarfile.open(filename)
    except tarfile.TarError:
        raise ReadError(
            "%s is not a compressed or uncompressed tar file" % filename)
    try:
        tarobj.extractall(extract_dir)
    finally:
        tarobj.close() 
Example #27
Source File: extract.py    From WordOps with MIT License 5 votes vote down vote up
def extract(self, file, path):
        """Function to extract tar.gz file"""
        try:
            tar = tarfile.open(file)
            tar.extractall(path=path)
            tar.close()
            os.remove(file)
            return True
        except tarfile.TarError as e:
            Log.debug(self, "{0}".format(e))
            Log.error(self, 'Unable to extract file \{0}'.format(file))
            return False 
Example #28
Source File: shutil.py    From Fluid-Designer with GNU General Public License v3.0 5 votes vote down vote up
def _unpack_tarfile(filename, extract_dir):
    """Unpack tar/tar.gz/tar.bz2/tar.xz `filename` to `extract_dir`
    """
    try:
        tarobj = tarfile.open(filename)
    except tarfile.TarError:
        raise ReadError(
            "%s is not a compressed or uncompressed tar file" % filename)
    try:
        tarobj.extractall(extract_dir)
    finally:
        tarobj.close() 
Example #29
Source File: utils.py    From rasa_core with Apache License 2.0 5 votes vote down vote up
def unarchive(byte_array: bytes, directory: Text) -> Text:
    """Tries to unpack a byte array interpreting it as an archive.

    Tries to use tar first to unpack, if that fails, zip will be used."""

    try:
        tar = tarfile.open(fileobj=IOReader(byte_array))
        tar.extractall(directory)
        tar.close()
        return directory
    except tarfile.TarError:
        zip_ref = zipfile.ZipFile(IOReader(byte_array))
        zip_ref.extractall(directory)
        zip_ref.close()
        return directory 
Example #30
Source File: shutil.py    From scylla with Apache License 2.0 5 votes vote down vote up
def _unpack_tarfile(filename, extract_dir):
    """Unpack tar/tar.gz/tar.bz2/tar.xz `filename` to `extract_dir`
    """
    try:
        tarobj = tarfile.open(filename)
    except tarfile.TarError:
        raise ReadError(
            "%s is not a compressed or uncompressed tar file" % filename)
    try:
        tarobj.extractall(extract_dir)
    finally:
        tarobj.close()