def cat_extract(tar, member, targetpath): """Extract a regular file member using cat for async-like I/O Mostly adapted from tarfile.py. """ assert member.isreg() # Fetch the TarInfo object for the given name and build the # destination pathname, replacing forward slashes to platform # specific separators. targetpath = targetpath.rstrip("/") targetpath = targetpath.replace("/", os.sep) # Create all upper directories. upperdirs = os.path.dirname(targetpath) if upperdirs and not os.path.exists(upperdirs): try: # Create directories that are not part of the archive with # default permissions. os.makedirs(upperdirs) except EnvironmentError as e: if e.errno == errno.EEXIST: # Ignore an error caused by the race of # the directory being created between the # check for the path and the creation. pass else: raise with files.DeleteOnError(targetpath) as dest: with pipeline.get_cat_pipeline(pipeline.PIPE, dest.f) as pl: fp = tar.extractfile(member) copyfileobj.copyfileobj(fp, pl.stdin) if sys.version_info < (3, 5): tar.chown(member, targetpath) else: tar.chown(member, targetpath, False) tar.chmod(member, targetpath) tar.utime(member, targetpath)